I'm trying to do an upsert where I $push a new element onto a field that is an array.
However, whenever I use $push I get the error telling me that I'm not allowed to use $ at the beginning of operators.
Here's the debug trace:
loopback:connector:mongodb create +3s ThingUser { user: 'gerald', '$push': { things: 'hats' } }
loopback:connector:mongodb MongoDB: model=ThingUser command=insert +2ms [ { user: 'gerald', '$push': { things: 'hats' }, _id: undefined },
{ safe: true },
[Function] ]
loopback:connector:mongodb Error: +5ms { [MongoError: key $push must not start with '$']
name: 'MongoError',
message: 'key $push must not start with \'$\'' }
loopback:connector:mongodb create.callback +0ms ThingUser { [MongoError: key $push must not start with '$']
name: 'MongoError',
message: 'key $push must not start with \'$\'' } null
It seems as though I'm not putting allowExtendedOperators in the correct place. I have tried everywhere where does this thing go? Can it not work with upsert?
Related
I’m having trouble with upsert with meteor.js. I could update questions finely with the below codes but I won’t be able to insert new data.
file in client side
const onSave = () =>{
// there is more codes but omitted
questions.forEach(question => {
Meteor.call('modifyQuestion', question);
})
}
file in server side (collection file)
modifyQuestion(question) {
check(question, Object);
const questionId = Measures.findOne({questionId: question._id});
Measures.upsert(
{_id: questionId._id},
{
$set: {
title: question.text,
},
},
);
},
Got error saying…
Exception while simulating the effect of invoking 'modifyQuestion' TypeError: Cannot read properties of undefined (reading '_id')
I thought when {_id: questionId._id} got undefined, that’s the time upsert understand that there is no matching data found and insert one as new data into the database.
Is this wrong?
I switched $set to $setOnInsert, but still didn't work...
ADDED
Now I don't see any error but i couldn't insert new data. I could update data tho.
modifyQuestion(question) {
check(question, Object);
Measures.upsert(
{questionId: question._id}, // changed
{
$set: {
title: question.text,
},
$setOnInsert: {type: 'multipleChoice'}
},
);
},
Also removed const questionId = Measures..... part
You still need to set the questionId on insert:
modifyQuestion(question) {
check(question, Object);
Measures.upsert(
{ questionId: question._id },
{
$set: {
title: question.text,
},
$setOnInsert: {
questionId: question._id
type: 'multipleChoice'
}
},
);
},
Otherwise there will never be a doc that contains the questionId.
Note: Another helpful tool would be Collection2 and define a schema, so it throws errors, in case docs are inserted/updated that violate a schema. Using this would have thrown, that questionId is missing on insert.
I have a blog collection whose schema is something like below
{
content:String,
type:String,
author:Number
}
Query
const edit = await Posts.findByIdAndUpdate(
{
_id: postId,
$or: [
{ type: "blog" },
{ author: 123 },
],
},
{
$set: {
content:"...new"
},
}
);
On executing this I am getting the below error
Error: Can't use $or
at ObjectId.SchemaType.castForQuery (/home/rahul/Desktop/projects/components/components-server/node_modules/mongoose/lib/schematype.js:1539:13)
at ObjectId.SchemaType.castForQueryWrapper (/home/rahul/Desktop/projects/components/components-server/node_modules/mongoose/lib/schematype.js:1511:22)
at cast (/home/rahul/Desktop/projects/components/components-server/node_modules/mongoose/lib/cast.js:316:39)
at model.Query.Query.cast (/home/rahul/Desktop/projects/components/components-server/node_modules/mongoose/lib/query.js:4963:12)
at castQuery (/home/rahul/Desktop/projects/components/components-server/node_modules/mongoose/lib/query.js:4764:18)
at model.Query.Query._findAndModify (/home/rahul/Desktop/projects/components/components-server/node_modules/mongoose/lib/query.js:3707:23)
at model.Query.<anonymous> (/home/rahul/Desktop/projects/components/components-server/node_modules/mongoose/lib/query.js:3267:8)
at model.Query._wrappedThunk [as _findOneAndUpdate] (/home/rahul/Desktop/projects/components/components-server/node_modules/mongoose/lib/helpers/query/wrapThunk.js:27:8)
But the same query is working with CLI mongo shell
db.posts.findOneAndUpdate({_id:ObjectId("postId"),$or:[{type:"blog"},{author:123}]},{$set:{content:"blog78"}})
I am getting this error when I try to update a record:
(node:2018) UnhandledPromiseRejectionWarning: MongoError: document must be a valid JavaScript object
Heres my code that I'm trying to run:
global.db.collection("groups").find({userId: user_id.toString(), groupNumber:parseInt(realGroupNumber)}).toArray( function (err, group) {
if(err) {console.log(err)};
if(group[0]) {
group[0].students.push(NewRow[row]);
//NOTE: HERE IS WHERE THE ERROR HAPPENS (BELOW)
global.db.collection("groups").update({userId: user_id.toString(), groupNumber:parseInt(realGroupNumber)}), group[0], function (err, group) {
if(err) {console.log(err)};
};
};
});
It keeps saying that group[0] is not a valid JavaScript object, but typeof group[0] returns 'object'.
Also here is an example of group[0] console logged out:
{ _id: 5df7fcc562f67c0a0b66aefd,
userId: '5d3f42db404e9e0a91fdd9d8',
groupNumber: 3,
selectedLeaders: [ '5df7d27e2e5e1904552a30a4' ],
roomNumber: '333',
groupNotes: '',
students:
[ { firstName: 'June',
userId: '5d3f42db404e9e0a91fdd9d8',
lastName: 'Lopez',
gender: 'female',
groupId: 3,
roomNumber: '1234',
_id: 5dfac3a34c64110809726571 } ] }
Any help greatly appreciated! Thanks!
It looks like the error is being caused by the closing parenthesis on line 7 below. This is closing the update, which excludes group[0] and the callback from being included:
global.db.collection("groups").update({
userId: user_id.toString(),
groupNumber: parseInt(realGroupNumber)
}), group[0], // <---- HERE
function(err, group) {
if (err) {
console.log(err)
};
};
Try moving it to the end of the block, after the callback:
//NOTE: HERE IS WHERE THE ERROR HAPPENS (BELOW)
global.db.collection("groups").update({
userId: user_id.toString(),
groupNumber: parseInt(realGroupNumber)
}, group[0],
function(err, group) {
if (err) {
console.log(err)
};
});
That said, note that collection.update() has been deprecated for some time. You should look into updating to at least a 3.X version of the Node driver and using updateOne or updateMany:
https://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#update
I have the following scrip in "script.js"
conn = new Mongo();
db = conn.getDB("learn");
db.contracts.aggregate([
{ $match: { regionCode: '77' } },
{ $unwind: '$products' },
{
$project: {
_id: '$_id',
regNum: '$regNum',
prodName: '$products.name',
prodPrice: '$products.price'
}
},
{ $match: { 'prodName' : 'Water' } }
], {cursor:{}}).result.forEach(printjson);
I run it from the command prompt by the following way
mongo script.js >> out.txt
In file "out.txt" I have the error
TypeError: Cannot call method 'forEach' of undefined at script.js
The same problem, when I run the script from mongo shell mongo.exe (by using load()).
When I run the same aggregate command from the Robomongo 0.8.4 I have succesive result (3 documents in json format). Does anybody know, why this may happen?
Mongodb version 2.6.5
You need to run it without the result variable access. The cursor returned by mongodb when accessed in the shell, does not have a property named result and hence you get the error.
db.contracts.aggregate([
{ $match: { regionCode: '77' } },
{ $unwind: '$products' },
{
$project: {
_id: '$_id',
regNum: '$regNum',
prodName: '$products.name',
prodPrice: '$products.price'
}
},
{ $match: { 'prodName' : 'Water' } }
], {cursor:{}}).forEach(printjson);
I create a database (wordinfo - nedb in memory), insert some data, and then retrieve the data (sorted) for print out with console.log. Too easy. Curiously, the console.log printout changes with the addition of a string:
wordinfo.find( { $and: [{index: {$lte: 10}},{index: {$gt: 5}}] }).sort({index: 1}).exec(function(err,docs) {
console.log(docs);
});
Which yields on the console:
11 Mar 09:51:46 - [nodemon] starting `node app.js`
Running myscripts
Express server listening on port 3000
[ { index: 6, value: 'Artistic', _id: 'XfudVdremMDODJWk' },
{ index: 7, value: 'Assertive', _id: 'utiSSGqGDwlD1olv' },
{ index: 8, value: 'Assessing', _id: 'zzhmecUhkUvCfnNA' },
{ index: 9, value: 'Autonomous', _id: 'QPGOZRXv48c9hvhV' },
{ index: 10, value: 'Blunt', _id: 'hrEBQ7tAXuZLAzSk' } ]
Now I change the print out request to include a little string identifying what is printing out ("Word info: ") like so:
wordinfo.find( { $and: [{index: {$lte: 10}},{index: {$gt: 5}}] }).sort({index: 1}).exec(function(err,docs) {
console.log('Word info: ' + docs);
});
Which yields something different on the console:
11 Mar 09:52:14 - [nodemon] starting `node app.js`
Running myscripts
Express server listening on port 3000
Word info: [object Object],[object Object],[object Object],[object Object],[obje
ct Object]
The 'docs' variable now prints out as the type of each record (object) instead of the content. Why? What is causing the change? Not a biggie, just curious. TIA for the assistance.
This is because you passed a string to console.log().
Console.log() accepts the docs object you used in your first example, however in your second example you concatenated your object with a string; console.log('Concatenation happens here' + docs), now the function doens't format your object as you wanted.
To correctly log an object pass them to the function: console.log('Word info: ', docs)
You can also format using %j: console.log('These objects were found: %j \n Yay!', docs)
Reference: https://developer.mozilla.org/en-US/docs/Web/API/console.log