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?