Reputation: 209
I have collection path_test
with 2 documents in it
Document 1
{
"_id" : 1,
"tpc" : 5,
"path" : [
{
"nids" : [ 0, 10, 11 ],
"ctc" : 2
},
{
"nids" : [ 0, 10 ],
"ctc" : 2
},
{
"nids" : [ 0, 10, 21 ],
"ctc" : 1
}
]
}
Document 2
{
"_id" : 2,
"tpc" : 5,
"path" : [
{
"nids" : [ 0, 10, 110 ],
"ctc" : 1
},
{
"nids" : [ 0, 10, 11 ],
"ctc" : 2
},
{
"nids" : [ 0, 5 ],
"ctc" : 2
}
]
}
What I'm trying to get as a result are documents with path
array in which all elements have nids
like [0, 10, *]
. Order is important, so [10, 0, *]
will be wrong.
It should find Document 1, but not Document 2. Was hoping I can resolve this with a query, before I start using map-reduce or aggregation.
This is what I've tried so far
Query1
db.getCollection('path_test').find( {
"path": { $not: { $elemMatch: { "nids.0": { $nin: [0] }, "nids.1": { $nin: [10] } } } }
});
Query 2
db.getCollection('path_test').find( {
"path.nids": { $not: { $elemMatch: { $nin: [0, 10] } } }
});
but both queries give me results where only 0 is in or where only 10 is in, but I need both and in that exact order.
Is that possible?
Upvotes: 3
Views: 353
Reputation: 6652
not at least one means noone
Query 1
For simplification, lets assign
A = "nids.0": { $ne: 0 }
B = "nids.1": { $ne: 10 }
C = { A, B }
then
{ "path" : { $elemMatch: C } }
will find documents where at least one element in path
array satisfies condition C
, while
{ "path" : { $not: { $elemMatch: C } } }
will find documents where there are no element in path
array that satisfies condition C
.
Document 1 and Document 2 don't have elements in their path
arrays that satisfy condition C
, thus the Query1 output contains both of them. If, f.e, you add to the path
array of the Document 1
{ "nids": [ 1, 11, 110], "ctc" : 1 }
then Document 1 will not be in the output of Query 1 becase this added element satisfies C
.
Query 2
For simplification, lets assign
C = { $nin: [0, 10] }
then
{ "path.nids" : { $not: { $elemMatch: C } } }
will find documents where there are no element in path.nids
array that satisfies condition C
.
Document 1 and Document 2 in their path.nids
arrays have elements that satisfy condition C
, thus the Query 2 output contains neither of them. If, f.e, you add to you collection document
{ "_id" : 6, "tpc" : 5, "path" : [ { "nids" : [ 0, 10 ], "ctc" : 1 } ] }
then it will be in the output of Query 2 because in path.nids
array there are no elements that satisfy C
.
Solution
In Query 1 replace
{ $elemMatch: { "nids.0": { $nin: [0] }, "nids.1": { $nin: [10] } } }
with
{ $elemMatch: { $or: [ { "nids.0": { $ne: 0 } }, { "nids.1": { $ne: 10 } } ] } }
This new Query will find documents where there are no element in path
array that satisfies at least one of conditions A
and B
. So, it will find Document 1, but not Document 2 (where "nids" : [ 0, 5 ]
does not satisfy condition B
.
Note that { $ne: 10 }
is equivalent to { $nin: [10] }
.
Upvotes: 2