Meteor Mongo update ($set object; $push array) - mongodb

Good Day.
I'm having difficulty figuring out why my mongo isn't updating. Objects and Arrays are not being updated. I've
been trying many avenues. Besides the code below, I've tried having the key already in the document (but empty, so
the array would be keyName:{} , as well as the key not in the document). I've also tried putting the keys within quotes, etc.
I've taken the console output of the update and pasted into Robo3T and ran the query and it updates the document just fine.
meteor 1.6
mongo 3.2.15
Server code running
const dbQuery = {owner: uid.user_id, paymentToken: uid.paymtToken}
exFile = {
$set: {
agreement_id: responseData.id, // string
selfUrl: responseData.links[0].href, // string
agreementDetails: responseData.agreement_details, // object
membershipLevel: 'premium', // string
ppOwnerInfo: responseData.payer, // object
},
};
let subsReturn = MonthlySubs.update(dbQuery, exFile, {multi:false, upsert:false} );
console.log('subsReturn: ', subsReturn); // outputs: 1
This will result in the document being update with everything except the objects. I know that exFile is valid:
console.dir(exFile, {depth: null});
results in:
{ '$set':
{ agreement_id: 'I-SW0AL8YJS',
selfUrl: 'https://api.sandbox.paypal.com/v1/payments/billing-agreements/I-SW0AL',
agreementDetails:
{ outstanding_balance: { value: '0.00' },
cycles_remaining: '1',
cycles_completed: '0',
next_billing_date: '2018-05-05T10:00:00Z',
final_payment_date: '1970-01-01T00:00:00Z',
failed_payment_count: '0' },
membershipLevel: 'premium',
ppOwnerInfo:
{ payment_method: 'paypal',
status: 'verified',
payer_info:
{ email: 'paypal-buyer#tion.com',
first_name: 'test',
last_name: 'buyer',
payer_id: '99CEFGB6L',
shipping_address:
{ recipient_name: 'test buyer',
line1: '1 Main St',
city: 'San Jose',
state: 'CA',
postal_code: '95131',
country_code: 'US' } } } } }
Also having issues with updating an array.
let pushFile = {
$push: {
links: {href: responseData.links[0].href, rel: 'self', method: 'GET', }
}
};
console.dir(pushFile, {depth: null});
subsReturn = MonthlySubs.update(dbQuery, pushFile, {multi:false, upsert:false} );
console.log('subsReturn: ', subsReturn); // outputs: 1
Here's the pushFile contents from the console output:
{ '$push':
{ links:
{ href: 'https://api.sandbox.paypal.com/v1/payments/billing-agreements/I-S45A17AV',
rel: 'self',
method: 'GET' } } }
This too works well in Robo3T.
I'm using simpl-schema:
[snip]
selfUrl: {
type: String,
label: 'Link for details about subscription on Paypal.',
optional: true,
},
ppOwnerInfo: {
type: Object,
label: 'Subscriber name, address, etc. from Paypal. Populates after subscription executed. (payer)',
optional: true,
},
links: {
type: Array,
label: 'Holds various Paypal endpoints. Optional because not all inserts/updates have these.',
optional: true,
},
[/snip]

In your schema you need to set blackbox: true for ppOwnerInfo. Likely also for agreementDetails see docs

Related

$push causing error Updating the path 'x' would create a conflict at 'x'

Given the example with Mongoose:
Schema:
const fields = {
...other fields
users: [
{ name: String, email: String, department: String, position: String, _id: false }
]
}
const Company = model('Company', fields);
Update action:
const companyId = 'company-id';
const user = { name: 'John', email: 'john#email.com' }
Company.findByIdAndUpdate(companyId, {
$push: {
users: user
}
}, { new: true })
.lean({ defaults: true })
.exec();
This causes an error:
Updating the path 'users' would create a conflict at 'users'.
I would think this would work correctly and I'm not doing anything else except pushing a new object to the array. Any help would be appreciated. Thanks!

Mongoose add or update values in an array inside an object inside an array

This is my schema,
const courseSchema = new mongoose.Schema({
name: String,
code: String,
class: String,
credit: Number,
overview: String,
prerequisite: String,
syllabus: [
{
moduleName: String,
moduleDetails: String,
},
],
materials: [
{
moduleNo: Number,
moduleMaterials: [String],
},
],
teacher: String,
students: [String],
});
I want to add new materials in which each time an update operation is called I receive a
moduleNo and a materialURL.
I want to add this to the materials array in my existing course which is filtered by courseID. So each time I receive a moduleNo and a materialURL, I want to check if moduleNo already exists in the materials array. If yes, then add materialURL into the moduleMaterials array without deleting the existing urls in moduleMaterials. If no, then add a new object with moduleNo and moduleMaterials and materialURL pushed into moduleMaterials. I've heard about upsert and think that could be used but I'm not sure what the correct queries are to do this operation.
What I've currently come up with even though it's wrong,
Course.updateOne(
{ _id: courseID },
{
$push: {
materials: { moduleNo, moduleMaterials: { $push: { materialURL } } },
},
},
{ upsert: true },
(err, result) => {
if (err) {
console.error(err);
} else {
console.log(result);
}
}
);
How do I do execute this query?

SailsJs: how to use find for array of object attribute?

i have a model that it has some json type attribute and now I want to use find on this json attribute. may please help how can i do it?
model:
module.exports = {
attributes: {
ownerInfo: {
type: 'json',
description: 'owner info of Task',
example: {id: '', fullName: '', emailAddress: ''}
},
name: {
type: 'string',
required: true,
description: 'Name of Task',
example: 'Business App'
},
users: {
type: 'json',
columnType: 'array',
description: 'Users id of task',
defaultsTo: [],
example: [{id :'', emailAddress: '', fullName: '', status: ['admin', 'leader', 'user']}]
}
}
}
actually i need 2 different query, one for finding ownerInfo.id and another else is finding user[].id.
in second query attribute is Array.
I searched a lot in Internet and tried many time with the queries like below but have not got any result.
tasks = await Task.find({
where: {
ownerInfo: {
id: params.id
}
}
})
for Array i had no any Idea how to search in Array of Object. please share your Idea.
tasks = await Task.find({
where: {
users: {
// how to search status of user ??
}
}
})
and also in MongoDb better I save short user info in task collection or like relative DB only keep the id of them and with populate reach that data? which method is faster and better as performance?
advanced thanks

Mongoose pull ObjectId from array

i'm trying to do a pretty simple operation, pull an item from an array with Mongoose on a Mongo database like so:
User.update({ _id: fromUserId }, { $pull: { linkedUsers: [idToDelete] } });
fromUserId & idToDelete are both Objects Ids.
The schema for Users goes like this:
var UserSchema = new Schema({
groups: [],
linkedUsers: [],
name: { type: String, required: true, index: { unique: true } }
});
linkedUsers is an array that only receives Ids of other users.
I've tried this as well:
User.findOne({ _id: fromUserId }, function(err, user) {
user.linkedUsers.pull(idToDelete);
user.save();
});
But with no luck.
The second option seem to almost work when i console the lenghts of the array at different positions but after calling save and checking, the length is still at 36:
User.findOne({ _id: fromUserId }, function(err, user) {
console.log(user.linkedUsers.length); // returns 36
user.linkedUsers.pull(idToDelete);
console.log(user.linkedUsers.length); // returns 35
user.save();
});
So it looks like i'm close but still, no luck. Both Ids are sent via the frontend side of the app.
I'm running those versions:
"mongodb": "^2.2.29",
"mongoose": "^5.0.7",
Thanks in advance.
You need to explicitly define the types in your schema definition i.e.
groups: [{ type: Schema.Types.ObjectId, ref: 'Group' }],
linkedUsers: [{ type: Schema.Types.ObjectId, ref: 'User' }]
and then use either
User.findOneAndUpdate(
{ _id: fromUserId },
{ $pullAll: { linkedUsers: [idToDelete] } },
{ new: true },
function(err, data) {}
);
or
User.findByIdAndUpdate(fromUserId,
{ $pullAll: { linkedUsers: [idToDelete] } },
{ new: true },
function(err, data) {}
);
I had a similar issue. I wanted to delete an object from an array, using the default _id from mongo, but my query was wrong:
const update = { $pull: { cities: cityId }};
It should be:
const update = { $pull: { cities: {_id: cityId} }};

MongoDB Document Validation in Meteor?

How would one approach doing this (https://docs.mongodb.com/v3.2/core/document-validation/):
db.createCollection( "contacts",
{ validator: { $or:
[
{ phone: { $type: "string" } },
{ email: { $regex: /#mongodb\.com$/ } },
{ status: { $in: [ "Unknown", "Incomplete" ] } }
]
}
} )
In this:
// database.js
import { Mongo } from 'meteor/mongo';
export const Test = new Mongo.Collection('Test');
Thanks
you first need to define your schema in meteor.
Lists.schema = new SimpleSchema({
name: {type: String},
incompleteCount: {type: Number, defaultValue: 0},
userId: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true}
});
This example defines a schema with a few simple rules:
We specify that the name field of a list is required and must be a
string.
We specify the incompleteCount is a number, which on insertion is
set to 0 if not otherwise specified.
We specify that the userId, which is optional, must be a string that
looks like the ID of a user document.
It’s pretty straightforward to validate a document with a schema. We can write:
const list = {
name: 'My list',
incompleteCount: 3
};
Lists.schema.validate(list);
In this case, as the list is valid according to the schema, the validate() line will run without problems. If however, we wrote:
const list = {
name: 'My list',
incompleteCount: 3,
madeUpField: 'this should not be here'
};
Lists.schema.validate(list);
Then the validate() call will throw a ValidationError which contains details about what is wrong with the list document.