Updating mongo document after it's been found - mongodb

I'm trying to update a number of documents from an array of object ids passed. I want to be able to update each document by pushing the userid into the visitor array.
i'm getting this error CastError: Cast to ObjectId failed for value. see my code below
var estates = req.params.estates.split(',');
Estate.findByIdAndUpdate({ _id: { $in: estates } }).then(function(Estate)
{
Estate.visitors.push(mongoose.Types.ObjectId( req.params.userid));
Estate.save();
});

according to mongoose documentations findByIdAndUpdate first param is an id which you are passing an object
try replacing it by findOne({ _id: { $in: estates } })

Your API usage is wrong, first argument for findByIdAndUpdate should be an id, it fails to cast array to id.
for matching and updating multiple documents,
you need to use updateMany
db.foo.updateMany({"_id" : { $in : [1,2,3] }},{$push : {test: 2}},{$upsert : false})
or update with multi : true option
db.store.update({"_id" : { $in : [1,2,3] }},{$push : {test: 2}},{$upsert : false, multi : true})
output
{ "acknowledged" : true, "matchedCount" : 3, "modifiedCount" : 0 }
Mongoose
Estate.update({ _id: { $in: estates } }, {$push : {visitors : req.params.userid}}, {multi : true, upsert : false})
Doc findByIdAndUpdate

Related

$push and $inc error when performing updateOne in Mongoose

Express.js is using Mongoose. I want to put the value in a particular document array and add the index value to +1.
I wrote the code as below.
await DocSchema.updateOne({ userId : <userId> }, {
$push : {
dataArr : {
$inc : { index : 1},
name : <username>,
age : <userage>
}
}
});
In addition, the field type of the model was set as follows:
...
dataArr : [
{
index : {
type : Number,
required : true,
unique : true
},
...
}
]
...
No error occurs when performing the actual query, but the index value is not visible. How should I modify the code?

mongoose find collection by _id in a list of array

Here's my Schema
var PositiveSchema = new mongoose.Schema({
schoolID: {
type: mongoose.Schema.Types.ObjectId, ref: 'School'
},
name: String,
restrictAwardTo: Object
})
Now restrictAwardTo saves the data in this format
"restrictAwardTo" : [
{
"_id" : "5c31907d908eb8404657cbf0",
"firstName" : "Admin 2a"
},
{
"_id" : "5c1a7677c98da061141475a8",
"firstName" : "Justice"
},
{
"_id" : "5c1a7677c98da061141475a9",
"firstName" : "Itik"
}
],
How can I search inside my document using one of the _id listed under restrictAwardTo? I tried the solutions given below
mongooseJS find docs with IDs in an array
mongoose query: find an object by id in an array but it returns empty.
in Robo3t db.getCollection('positives').find({ 'restrictAwardTo._id' : ObjectId('5c31907d908eb8404657cbf0') })
Update: In Robo3t, this query db.getCollection('positives').find({ 'restrictAwardTo._id' : {$in: ['5c1a7677c98da061141475a7']} }) works. Now I'm making it work for mongoose too.
Here's the mongoose that works for me:
Positive.find({ schoolID: mongoose.mongo.ObjectId(schoolID), "restrictAwardTo._id": { $in: [userID]} })
But I'm not entirely sure of the performance for large records.
You could go through this way.
Positive.findOne({'restrictAwardTo': {$elemMatch: {_id: userID}}},
(err,schoolInfo) => { });

check if value exists in array field in mongodb

I want to check if user id exists inside an array field of mongodb (using meteor)
db.posts.find().pretty()
{
"_id" : "hT3ezqEyTaiihoh6Z",
"body" : "hey\n",
"authorId" : "AyJo5nf2Lkdqd6aRh",
"createdAt" : ISODate("2016-05-13T06:19:34.726Z"),
"updatedAt" : ISODate("2016-05-13T06:19:34.726Z"),
"likecount" : 0,
"already_voted" : [ ] }
db.posts.find( { _id:"hT3ezqEyTaiihoh6Z"},{ already_voted: { $in : ["AyJo5nf2Lkdqd6aRh"]} }).count()
1
It gives count value 1 , where as I am expecting it to be 0 .
Your logic is fine. Just the syntax is wrong.
db.posts
.find({
_id: "hT3ezqEyTaiihoh6Z",
already_voted: { $in: ["AyJo5nf2Lkdqd6aRh"] },
})
.count();
This should work.
You can just simply use count method. Don't need to use two operation like Find and then count.
db.posts
.count({
_id: "hT3ezqEyTaiihoh6Z",
already_voted: { $in: ["AyJo5nf2Lkdqd6aRh"] }
});

Mongoose Mongodb sorting and limiting query of subdocuments

I've got the following design Schema:
{
participants: [String],
conversations: [{
date: Date
messages: [String]
}]
}
Now i want to get the 6 newest converations. I have tried a lot but i can't seem to find the solution. I can sort by subdocuments, but at the end if 1 document has the 6 newest conversations the query will end up giving me this one document plus 5 others. I woud like to get an array like this at the end of the query or be able to get this particular information:
[{date:'Adate', messages:[]},{date:'Adate2',messages:[]}]
Thanks for your help!
Actually this is not possible with the single query if you are a using a mongoDB version LESS than 3.1.6.
$Slice is supported in aggregation pipeline in the mongoDB version 3.1.6 and above
If your mongoDB version is below 3.1.6, then you can try the below piece of code :
db.collection.aggregate([
{ $unwind : "conversations"},
{ $sort : {_id : 1, conversations.date : -1}},
{ $group: { _id : "$_id"} , conversations : { $push : "$conversations"}, participants : {$first : "$participants"} },
{ $project : { _id : 1, conversations : 1, participants : 1 } }
]).forEach( function(doc)
{
if( doc.conversations.length > 6)
{
var count = doc.conversations.length - 6;
doc.conversations.splice(6, count );
}
}
)
There is a similar question on the StackOverflow for the version below 3.1.6, Please check the link.
For the mongoDb Version 3.1.6 and above, you can use $Slice in aggregation pipeline to limit the contents of array.
Try the below code :
db.collection.aggregate([
{ $unwind : "conversations"},
{ $sort : {_id : 1, conversations.date : -1}},
{ $group: { _id : "$_id"} , conversations : { $push : "$conversations"}, participants : {$first : "$participants"} },
{ $project :
{
_id : 1,
participants : 1,
newconversations :
{
conversations : { $slice : 6 }
}
}
}
])

mongodb update and/or change an array key without using the value

I'm having trouble removing/renaming an array object from my mongodb.
{
"_id" : ObjectId("556a7e1b7f0a6a8f27e01b8a"),
"accountid" : "AC654164545",
"sites" :[
{ "site_id" : "example1.com" },
{ "002" : "example2.com" },
{ "003" : "example3.com" },
{ "004" : "example4.com" },
{ "005" : "example5.com" },
{ "006" : "example6.com" }
]}
}
Please take notice of the array key "site_id", I want to change it to "001" by either removing and appending it, which I know how to do, or rename it.
I've tried:
db.accounts.update({'id':ObjectId("556a7e1b7f0a6a8f27e01b8a")}, {$unset: {sites.site_id}})
But that says "unexpected token".
So I tried:
db.accounts.update({'id':ObjectId("556a7e1b7f0a6a8f27e01b8a")}, {$unset: {sites:site_id}})
That says "site_id is not defined"
Then I tried:
db.accounts.update({'id':ObjectId("556a7e1b7f0a6a8f27e01b8a")}, {$unset: {sites:'site_id'}})
That says WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
I also tried a $rename command:
db.accounts.update( { _id:ObjectId("556a7e1b7f0a6a8f27e01b8a") }, { $rename: { "sites.site_id": "sites.001" } } )
But that gave me a "Cannot use part (sites of sites.site_id) to traverse the element"
One option would be to use .find(), iterate through and delete it. Save the undeleted ones into an object, and run an .insert() command, but I want to stay away from that if I have too.
This site talks about dynamic renaming: http://docs.mongodb.org/manual/reference/operator/update/positional/
Aka first you make a matching query and then you use the $ to match that to the index in the array.
Here's the query that'll accomplish what you want for the test data you provided:
db.accounts.update({'accountid':"AC654164545", "sites.site_id": "example1.com"}, {$set: {"sites.$": {'001': 'example1.com'}}})
It is not recommended to use dynamic values such as numbers as a key in document structure. This will be more difficult to query using such values.
You can use $set and $elemMatch to get result as following:
db.collection.update({
'_id': ObjectId("556a7e1b7f0a6a8f27e01b8a"),
"sites": {
$elemMatch: {
"site_id": "example1.com"
}
}
}, {
$set: {
"sites.$":{"001": "example1.com"}
}
})