I'm trying to run the following queries with the data inserted as follows. For whatever reason the $ne with 0 in the value doesn't seem to work. I tried this on both linux and mac using v2.0.4. Also ran these using the mongo shell.
Anybody have any ideas? Is this a bug or something I'm misunderstanding?
db.associated.insert({
"diskinfo" : {
"physical" : [
{"merror_count" : "Count: 0"},
{"merror_count" : "Count: 0"},
{"merror_count" : "Count: 0"},
{"merror_count" : "Count: 509"}
]
}})
db.associated.insert({
"diskinfo" : {
"physical" : [
{"merror_count" : "Count: 0"},
{"merror_count" : "Count: 5"},
{"merror_count" : "Count: 0"}
]
}})
db.associated.insert({
"diskinfo" : {
"physical" : [
{"merror_count" : "Count: 0"},
{"merror_count" : "Count: 0"},
{"merror_count" : "Count: 0"}
]
}})
ran these queries on the mongo shell. and got the results in the comments
db.associated.find( { "diskinfo.physical.merror_count" : { $ne : 'Count: 0'}}).count() // Result: 0, Expected: 2 db.associated.find( { "diskinfo.physical.merror_count" : { $ne : 'Count: 509'}}).count() // Result: 2, Expected: 2 db.associated.find( { "diskinfo.physical.merror_count" : { $ne : 'Count: 5'}}).count() // Result: 2, Expected: 2
Although this is an old question I think there is still place for some additional explanation about the semantics of $ne with arrays.
It is well-known that the behavior of mongo with queries of the form
db.collection.find({a:v})
when a is an array: it returns all the documents such that (at least) one element in the array key is v. In the example:
db.associated.find({"diskinfo.physical.merror_count" : "Count: 0"}).count()
returns 3 because the the array "diskinfo.physical.merror_count" contains a value "Count: 0" in the three documents of the collection.
Then, it seems reasonable (at least is a possibility) to expect that
db.collection.find({a:{$ne:v}})
will return the documents such that the a contains something different from v. However, this is not the behavior in Mongo. Instead, the use of $ne indicates that only those documents whose array a does not contain v are selected.
This semantics can seem odd at the beginning but makes sense if we consider that in this way the expression:
db.collection.find({a:v}).count() + db.collection.find({a:{$ne:v}}).count()
return the total number of elements in the collection. Thus, in the example it makes sense that
db.associated.find({"diskinfo.physical.merror_count" : {$ne: "Count: 0"}}).count()
returns 0, because the array "diskinfo.physical.merror_count" contains at least one occurrence of "Count: 0" in the 3 documents of the collection.
These results are correct.
Your expectation may be based on the number of elements in the embedded array which match your predicate. However, it's the number of documents that satisfy the query that you will be getting back.
In the first case you query for all documents which don't have diskinfo.physical.merror_count equal to 'Count: 0'. Every document has diskinfo.physical.merror_count that's 'Count: 0' so you get back 0.
Look at it this way, every document in your collection has a diskinfo.physical.merror_count value that's something other than 'Count: 0'. If you queried with equality instead of inequality you would get back all three.
Are you trying to find all documents which have only entries that are 'Count: 0'?
There doesn't seem to be a straight forward way to do this, but one query that would get you this would be:
db.associated.find( { "diskinfo.physical.merror_count" : { $gt : 'Count: 0'}}).count()
At least this would be the solution if the counts were actually integers - it happens to work with strings as well because "1">"0", etc.
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