Updating Multiple Documents In MongoDB Based on ID - javascript

So I've seen this question asked before, but when I tried the solution myself it didn't seem to work. Update multiple documents by id set. Mongoose
Based on the solution above, I wrote this code:
listOfParticipant = [ "5f50a1df63fe0000ed98b393", "5f69cc7cda1d549f9edcc8bb","5f3207204450b32620449657","5f3207204450b32620449657", "5f39585030027a3d57f0cc0e", "5e719e4715c7865bcb00c820", "5f32d0ab59eccf22d2e2f29f" ],
User.update( {_id: {$in: listOfParticipant}},
{$addToSet: {
userNotification: notification
}
},
{multi: true}
)
But it doesn't seem to work, could anyone help me out in finding out why?

So this query is correct. The reason it wasn't working is because I was trying to chain it with another MongoDB call. I was trying to use it inside the callback function when I updated another MongoDB collection. Once I made this into its own separate function, it worked just fine!

Related

Faceting on Search multiple indexes feature from Algolia

I am running a query on more than one of my indexes (by using this and everything works fine. Now, I want to implement a faceted search using such functionality (this) but I am not being able to do it since I don't instantiate an index per each query I want to run. I tried to find some information out there about this but I was not able to find a solution for my problem and I want to avoid instantiating multiple indexes. Ideas?
This is a piece of the code I am using to search with multiple queries:
query.push({
indexName: 'My Index',
query: 'My Query', //I would like to use here something like 'NOT customAttr:"my value"'
params: {
hitsPerPage: 5
}
});
client.search(query, function searchDone(){});

Pushing new item to a mongoDB document array

I've looked through a bunch of other SO posts and have found different ways to do this, so I'm wondering which is most preferred. I'm teaching this to students, so I want to give them best practices.
If I have the following BlogPost object (Simplified):
var BlogPostSchema = new mongoose.Schema({
body: String,
comments: [String]
});
and I want to add a new comment to the array of comments for this blog, I can think of at least 3 main ways to accomplish this:
1) Push the comment to the blog object in Angular and submit a PUT request to the /blogs/:blogID endpoint, updating the whole blog object with the new comment included.
2) Submit a POST request to a /blogs/:blogID/comments endpoint where the request body is just the new comment, find the blog, push the comment to the array in vanilla js, and save it:
BlogPost.findById(req.params.blogID, function(err, blogPost) {
blogPost.comments.push(req.body);
blogPost.save(function(err) {
if (err) return res.status(500).send(err);
res.send(blogPost);
});
});
OR
3) Submit the POST to a /blogs/:blogID/comments endpoint with the request body of the new comment, then use MongoDB's $push or $addToSet to add the commend to the array of comments:
BlogPost.findByIdAndUpdate(
req.params.blogID,
{$push: {comments: req.body}},
{safe: true, new: true},
function(err, blogPost) {
if (err) return res.status(500).send(err);
res.send(blogPost);
});
});
I did find this stackoverflow post where the answerer talks about option 2 vs. option 3 and basically says to use option 2 whenever you can, which does seem simpler to me. (And I usually try to avoid methods that stop me from being able to use hooks and other mongoose goodies.)
What do you think? Any advice?
From application point of view, point 3 is better. The reason I think are.
The query itself specifies what we are trying to achieve. it's
easily readable.
save function is a wild card, so we don't know what it's going to change.
if you fetch the document and manipulate it and then call save it, there is outside but real chance that you might mess up some
other field of the document in process of manipulation
unintentionally, not the case with point 3.
In case of addToSet,basically the previous point is more visible.
Think about the concurrency, if multiple calls comes with different comment for same blog and you are trying option 2, there
is a chance that you might override the changes which were done in
between you fetched the document and when you are saving it. Option
3 is better in that sense.
Performance wise they both do the same thing, so there might not be much or any visible difference. But option 3 is bit safer and cleaner.

Fetch associations on create or save with Sequelize

Fairly simple problem, just cant find the good/clean way to do this without making a call to another find
I've got my node app rigged up with Angular-Resource, and I'm just making some round-trip like data calls on new or changed data.
So ngResource making the $save() call to my /api/users/:id and such. And Node reacts to this call by creating or finding the user, making the updates, and saving them.
Whether through create() or save(), it returns the created record, and for right now, I use res.json(user) to spill the created/returned record for my Angular to handle populating my view with the updated information
Now, I know with Sequelizes find() and findAll() methods, I can use findAll({ include: [{ all: true }]}) or specify my models individually.
What I want to know is, what is the best way to get my records associations on save/create
and unfortunately, this just doesn't work:
models.User.create(newuser, {include:[{ all: true }]}).then(function(user) {
res.json(user);
});
Do I really have to perform another find() just to get my managed models associations?
To better illustrate the opted solution from RedactedProfile's comment, here's the code.
models.User
.create(newuser, {include:[{ all: true }]})
.then(user => {
user.reload().then(user => { res.json(user); })
});

MongoDB: incorrect update count

In my database, I have a field called 'fruits' which is a simple array. When inserting elements in this array, I use $addToSet to only insert elements that do not exist already in this array.
I want to know whether or not the element I insert really modified this field. However, the docModified parameter in the callback always returns 1 even when I try to add an element that already exists.
model.update (
{ username: username }, // find the document
{ $addToSet : { fruits: "apple" } }, // add "apple" to fruits field
function (err, docModified) {
console.log(docModified);
// !PROBLEM: this will print "1" no matter what
}
);
Does anyone know why? Thanks a lot! (btw I'm using Mongoose)
The current method implementations in mongoose use the legacy write concern API to determine the count of modified documents. As you note, even if there is no actual change to the content such as an $addToSet operation that does not add a new member to the set, the modified count will be returned.
As long as your MongoDB server version is recent enough ( needs to be MongoDB 2.6 or greater ) and your mongoose version is recent enough an bundles a recent mongodb driver, then you can get the correct numbers from the Bulk Operations API responses.
To do this with mongoose you call the .collection accessor on the model, which returns a native driver collection object:
var bulk = Model.collection.initializeOrderedBulkOp();
bulk.find({ username: username })
.updateOne({ $addToSet : { fruits: "apple" } });
bulk.execute(function(err,result) {
if (err) throw err;
console.log( JSON.stringify( result, undefined, 4 ) );
})
The "result" that is returned is an object conforming to the BulkWriteResult() specification, which more or less will look like this:
{
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 2,
"nUpserted" : 0,
"nMatched" : 3,
"nModified" : 3,
"nRemoved" : 1,
"upserted" : [ ]
}
But specifically, where you use $addToSet and the member already exists, the response will contain "nMatched": 1 and "nModified": 0, which is the result you want to see, confirming that nothing was in fact added to the set.
In the MongoDB 2.6 shell, all of the update and insert methods try to use this API where it is available and only fallback to the legacy implementation when connecting to an older server. So If you did this in a modern shell with a modern server you would see the same results.
Hopefully mongoose itself will be altered to also use these methods where available and provide access to the same response. It seems to be the way of the future, but the codebase is yet to catch up and utilize this.
Note: The one thing to be careful of when using any of the native driver methods after accessing the collection object is to make sure that mongoose has an active connection to the database at the time this is called. Mongoose hides this by queuing up any request until a connection is actually established.
So if you are going straight to the collection object methods, then you might want to make sure you are waiting for the "open" event on the connection somewhere before that code executes.
"number affected is the number of docs updated, even if the new values are identical. this comes straight from mongo." I got this from this forum post: https://github.com/LearnBoost/mongoose/issues/867
This means you'll have to come up with a different way to determine if the element was missing from the array before you update. I would recommend pull all the documents and iterating through them before the update. Obviously it's not ideal, but i don't think there's any other way to do it.
Hope this helps.

Search and replace in MongoDB collection

I have a mongo collection that contains a field called "url", storing an url.
Some of those urls have an extra parameter that bothers me, "id=<>" where <> can have any size
Can i do this in a update operation or do i need to write a script that will iterate and replace?
db.find({{"url": /.&id=.*/ }}).update(???)
Your best bet is going to be to explore use of the "multi" parameter in conjunction with field update parameters, as described at these locations on the MongDB website.
http://docs.mongodb.org/manual/reference/operator/update-field/
http://docs.mongodb.org/manual/reference/method/db.collection.update/#multi-parameter
An example is provided here:
http://docs.mongodb.org/manual/reference/method/db.collection.update/#example-update-multi
The issue is that you won't be able to implement any sort of "capturing group" functionality that just gets rid of the "id" parameter for each document though. There is a ticket open on MongoDB's jira account though detailing this behavior (currently in unresolved state):
https://jira.mongodb.org/browse/SERVER-9159
Try this to find documents using this regEx and then do update accordingly.
db.find({
"url": /id=\<.+\>/
}, function(err, result) {
//your code
})

Categories