MongoDB: how to do something like this, both in mongo console and via JavaScript, Node.js:
db.turnys.find( { users:{$size:seats } } )
turnydb.turnys looks like this:
[
{
"gId": "5335e4a7b8cf51bcd054b423",
"seats": 2,
"start": "2014-03-30T14:23:29.688Z",
"end": "2014-03-30T14:25:29.688Z",
"rMin": 800,
"rMax": 900,
"users": [],
"_id": "533828e1d1a483b7fd8a707a"
},
{
"gId": "5335e4a7b8cf51bcd054b423",
"seats": 2,
"start": "2014-03-30T14:23:29.688Z",
"end": "2014-03-30T14:25:29.688Z",
"rMin": 900,
"rMax": 1000,
"users": [],
"_id": "533828e1d1a483b7fd8a707b"
},
...
]
There are real problems with the acceptance of using the $where
operator in any sort of way. Especially considering some of your "later" questions that have been raised. You need to read the manual page on this operator (as given in the link).
The short points:
The $where
operator invokes a full collection scan in order to do it's comparisons. This is bad news in "real world" cases since there is no way to "constrain" this search to use an index in any way, and thus reduce the working set.
By nature, this operator invokes "arbitrary JavaScript execution". And this means two things. 1.) Every document must be expanded from it's native BSON form into the "JavaScript" object form (at a cost) for each comparison. 2.) You are invoking a "JavaScript" interpreter, that is not native code, for each and every comparison.
One of the answers gave you valid warnings on this, though it did not provide you with an actual answer. So here it is:
As stated, yes you should actually be keeping a "count" of the "array" elements within your document if this is important to you. But whilst you may have seen this as valid, the proper comparison is done as follows.
So let us assume you did use $inc
as suggested to keep a total_users
field in your document.
db.collection.aggregate([
{ "$project": {
"gId": 1,
"alloc": { "$eq": [ "$total_users", "$seats" ] }
}},
{ "$match": { "alloc": 1 } }
])
Where essentially you can $project
all the fields you want in the document, just as long as you make the comparison as shown with the "alloc" field by simply doing a "logical" comparison as shown with the $eq
operator.
In future releases ( very soon as of writing ) you even get to find out the $size
of an array within the "aggregation" operation. So "instead" of keeping a counter on the "array" members you can do this:
db.collection.aggregate([
{ "$project": {
"gId": 1,
"alloc": { "$eq": [ { "$size": "$users" }, "$seats" ] }
}},
{ "$match": { "alloc": 1 } }
])
But naturally that will come with a "cost", so still the best option is to keep that "counter" on your document, depending on your needs.
While both approaches here do *still** result in a "collection scan" (in this context since there was no other $match condition), the end result will be many times faster than the "JavaScript" execution that was shown in other answers.
Use the "native code" methods as a best practice solution.
You can use a $where
query:
db.turnys.find({ $where: "this.users.length == this.seats" })
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With