Count the number of items with a condition in MongoDB collection - javascript

I can't figure out what I'm doing wrong with my query. I want to get the number of "alertes" with the field "resolved: false" so my query is :
Alertes.find({resolved: false}).count();
But it returns me 0 despite I have 1 entry in the collection with the field resolved: false
Somone could help me to figure out what I'm doing wrong ?

I had forgot to subscribe to the collection in my IronRouter file :
Router.route('/', {
name: 'home',
waitOn: function() {
return [
Meteor.subscribe('infosContainers'),
Meteor.subscribe('infosMachines'),
Meteor.subscribe('alertes'),
];
},
fastRender: true,
});
Thank you for the help

Did you try this?
Alertes.find({resolved: false}).fecth().length
If you are running this code at the client side, make sure you have subscribed to this collection, and that you have documents that satisfy the filter you are looking for.
Try to query all documents (with no filter) to make sure the documents are there with the query above, and check what you get back:
Alertes.find().fecth()
If you don't find any documents with the resolved property set to false, then the query is returning correctly, and the problem is your subscription.

Related

Updating Multiple Documents In MongoDB Based on ID

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!

How can I add a special Mongo expression to a JSON object?

So I'm aware how I should add any regular string/object to a JSON object - however, I need to add the following Mongo command to my JSON object:
$set : { "author" : req.body.name }
As you can see, it's not as simple as just doing:
myJsonObject.author = "$set..." etc.
Sorry if this is a dupe question - this isn't the easiest subject to Google without tons of unrelated answers popping up.
The reason I need to know this because I want to be able to build a JSON object based on what the user has changed in the form. So a new problem I have encountered is that even if I can build the JSON object with multiple items to change, MongoDB only updates the last item in the object. My example JSON object is here:
updateItem = {
$set : { "name" : "Squid bonobo" },
$set : { "author" : "Mardy Bum" }
};
and the snippet of code which issues the update command is as follows:
updateData.update(searchItem, updateItem, false, true, function(err, results) {
console.log(results);
db.close();
});
I found this solution at the following git site.
Can anybody help with either of these questions?
Thanks for your help :)
Cameron
You need to form your JSON in the below structure:
updateItem = {
$set : { "name":"Squid bonobo","author":"Mardy Bum"}
}
Javascript Objects can be declared with duplicate keys/properties, but their values get over-written, with the latest bound value for the key, in any order.
Here, $set is a key/property which has been set twice to the same object referenced by the variable updateItem, hence only one value, that is last encountered, will be associated to the key. In this case, the value that takes precedence is:
$set:{ "author":"Mardy Bum" }
and the final query that gets executed becomes,
updateItem = {
$set : { "author" : "Mardy Bum" }
};

mongoose - how do I get the elements removed from $pull

I'm using $pull to pull a subdocument within an array of a document.
Don't know if it matters but in my case the subdocuments contain _id so they are indexed.
Here are JSONs that describes the schemas:
user: {
_id: String,
items: [UserItem]
}
UserItem: {
_id: String,
score: Number
}
Now my problem is this: I am using $pull to remove certain UserItem's from a User.
var delta = {$pull:{}};
delta.$pull.items={};
delta.$pull.items._id = {$in: ["mongoID1", "mongoID2" ...]};
User.findOneAndUpdate(query, delta, {multi: true}, function(err, data){
//whatever...
});
What i get in data here is the User object after the change, when what i wish to get is the items that were removed from the array (satellite data).
Can this be done with one call to the mongo or do I have to do 2 calls: 1 find and 1 $pull?
Thanks for the help.
You really cannot do this, or at least there is nothing that is going to return the "actual" elements that were "pulled" from the array in any response, even with the newer WriteResponse objects available to the newer Bulk Operations API ( which is kind of the way forward ).
The only way you can really do this is by "knowing" the elements you are "intending" to "pull", and then comparing that to the "original" state of the document before it was modified. The basic MongoDB .findAndModify() method allows this, as do the mongoose wrappers of .findByIdAndUpdate() as well and .findOneAndUpdate().
Basic usage premise:
var removing = [ "MongoId1", "MongoId2" ];
Model.findOneAndUpdate(
query,
{ "$pull": { "items._id": { "$in": removing } } },
{ "new": false },
function(err,doc) {
var removed = doc.items.filter(function(item) {
return removing.indexOf(item) != -1;
});
if ( removed.length > 0 )
console.log(removed);
}
);
Or something along those lines. You basically "turn around" the default mongoose .findOneAndUpdate() ( same for the other methods ) behavior and ask for the "original" document before it was modified. If the elements you asked to "pull" were present in the array then you report them, or inspect / return true or whatever.
So the mongoose methods differ from the reference implementation by returning the "new" document by default. Turn this off, and then you can "compare".
Further notes: "multi" is not a valid option here. The method modifies "one" document by definition. Also you make a statement that the array sub-documents conatain an _id. This is done by "mongoose" by default. But those _id values in the array are "not indexed" unless you specifically define an index on that field. The only default index is the "primary document" _id.

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.

BackboneJS collection.reset() vs collection.fetch()

I have read and read the docs on these two methods, but for the life of me cannot work out why you might use one over the other?
Could someone just give me a basic code situation where one would be application and the other wouldn't.
reset sets the collection with an array of models that you specify:
collection.reset( [ { name: "model1" }, { name: "model2" } ] );
fetch retrieves the collection data from the server, using the URL you've specified for the collection.
collection.fetch( { url: someUrl, success: function(collection) {
// collection has values from someUrl
} } );
Here's a Fiddle illustrating the difference.
We're assuming here that you've read the documentation, else it'l be a little confusing here.
If you look at documentation of fetch and reset, what it says is, suppose you have specified the url property of the collection - which might be pointing to some server code, and should return a json array of models, and you want the collection to be filled with the models being returned, you will use fetch.
For example you have the following json being returned from the server on the collection url:
[{
id : 1,
name : "a"
}, {
id : 2,
name : "b"
}, {
id : 3,
name : "c"
}]
Which will create 3 models in your collection after successful fetch. If you hunt for the code of collection fetch here you will see that fetch will get the response and internally will call either reset or add based on options specified.
So, coming back to discussion, reset assumes that we already have json of models, which we want to be stored in collection, we will pass it as a parameter to it. In your life, ever if you want to update the collection and you already have the models on client side, then you don't need to use fetch, reset will do your job.
Hence, if you want to the same json to be filled in the collection with the help of reset you can do something like this:
var _self = this;
$.getJSON("url", function(response) {
_self.reset(response); // assuming response returns the same json as above
});
Well, this is not a practice to be followed, for this scenario fetch is better, its just used for example.
Another example of reset is on the documentation page.
Hope it gives a little bit of idea and makes your life better :)
reset() is used for replacing collection with new array. For example:
#collection.reset(#full_collection.models)
would load #full_collections models, however
#collection.reset()
would return empty collection.
And fetch() function returns default collection of model

Categories