I have a Mongo document which has a list of items. Each of those items has some status associated with it.
I want to use $elemMatch
to return documents who have statuses which match certain criteria.
Consider the following document. It represents an order, and each item in the order is different (they represent eyeglasses):
{
"_id" : ObjectId("5335dcd6888a4f21dd77657c"),
"items" : [
{
"lens_type" : "STANDARD_INDEX_LENS",
"status" : {}
},
{
"lens_type" : "NO_LENS",
"status" : {
"shipped" : true
}
},
{
"lens_type" : "RX_SUN_LENS",
"status" : {
"received_from_lab" : true,
"sent_to_lab" : true,
"shipped" : true
}
}
]
}
I want to find all items which are "unshipped" - that is, items.status.shipped
does not exist. I want to find all items which are ready to be shipped.
However, if the item has a prescription lens - lens_type
is either STANDARD_INDEX_LENS
or RX_SUN_LENS
- then I only consider it unshipped if it has been received from the lab. item.status.received_from_lab
exists.
The above document should not be returned by my query. This is because two of the items have been shipped, and the other item is unshipped but has not yet been received_from_lab
.
However, my query is indeed returning this document!
Here is my query:
{
"$and": [
{
"items": {
"$elemMatch": {
"lens_type": {
"$in": [
"STANDARD_INDEX_LENS",
"RX_SUN_LENS"
]
},
"status.received_from_lab": {"$exists": true}
}
}
},
{
"items": {
"$elemMatch": {
"status.shipped": {"$exists": false}
}
}
}
]
}
What is the logic error in my query? What construct should I be using instead? Will I need to do this kind of filtering on the client side?