问题
I want to find all results where the array fieldB does not have values (val1 and val2) in fieldC objects.
I have tried:
db.SalesToImport
.find(
{
fieldA: {$exists:true},
,fieldB: {$not: {$elemMatch: {fieldC: 'val1'}}}
,fieldB: {$not: {$elemMatch: {fieldC: 'val2'}}}
}
);
And I have tried:
db.SalesToImport
.find(
{
fieldA: {$exists:true},
,fieldB: {$not: {$elemMatch: {fieldC: 'val1', fieldC: 'val2'}}}
}
);
They both yield the same results and while they remove some documents, there are still docs with val1
and val2
in them, which tells me that I made an incorrect query.
A document's structure contains fields like so:
{
fieldA: value,
fieldB: [
{fieldC:value1, fieldD:value3, fieldE:value5},
{fieldC:value2, fieldD:value4, fieldE:value6}
]
}
How should I combine $elemMatch with $nin or $not in a MongoDB query to get the desired effect?
Update # 1
Based on the suggestions I ran the following realistic but sanitized query:
db.SalesToImport
.find(
{
calculatedTaxRate: {$exists:true}, unidentifiedProducts: {$exists:false}, unidentifiedCustomer: {$exists:false},
register_sale_payments: {
$elemMatch: {
retailer_payment_type_id : {
$nin: [
'0af7b240-ab24-11e7-eddc-9fff6de134e9'
,'0af7b240-ab24-11e7-eddc-9fff69293826'
]
},
}
}
},
{_id:0,status:0,customer_id:0,register_id:0}
)
.sort({"calculatedTaxRate":1});
But the response still had the unwanted results in fieldB.fieldC
or register_sale_payments.retailer_payment_type_id
, so this wasn't what I was looking for or I made a mistake in using it.
Update # 2
Based on the suggestions I ran the following realistic but sanitized query:
db.SalesToImport
.find(
{
calculatedTaxRate: {$exists:true}, unidentifiedProducts: {$exists:false}, unidentifiedCustomer: {$exists:false},
'register_sale_payments.retailer_payment_type_id': {
$nin: [
'0af7b240-ab24-11e7-eddc-9fff6de134e9'
,'0af7b240-ab24-11e7-eddc-9fff69293826'
]
}
},
{_id:0,status:0,customer_id:0,register_id:0}
)
.sort({"calculatedTaxRate":1});
and it worked!
回答1:
While you are interested just one field of fieldB
, you don't need to use $elemmatch
.
db.SalesToImport.find(
{
"fieldA": {$exists:true},
"fieldB.fieldC": { $nin: ["val1", "va2"] }
}
);
If you have a fieldD in fieldB
and for example, you don't want fieldD have values val3, val4 too :
db.SalesToImport.find(
{
"fieldA": { $exists: true },
"fieldB.fieldC": { $nin: ["val1", "va2"] },
"fieldB.fieldD": { $nin: ["val3", "va4"] }
}
);
Above query exclude documents for fieldC, fieldD pairs like that too: (val5, val3), because we are querying fieldC and fieldD seperately.
If you want to query for fieldB
not have value pairs for fieldC and fieldD (val1, val3), (val1, val4), (val2, val3), (val2, val4) :
db.SalesToImport.find(
{
"fieldA": { $exists: true },
"fieldB": { $elemmatch: {
"fieldC" : { $nin: ["val1", "val2"] },
"fieldD": { $nin: ["val3", "val4"] } }
}
}
);
Above query does not exclude filedC, fieldD pairs like: (val5, val3)
来源:https://stackoverflow.com/questions/46375888/how-to-combine-elemmatch-with-nin-or-not-in-a-mongodb-query