Mongodb 对$elemMatch使用多个条件

Mongodb 对$elemMatch使用多个条件,mongodb,mongodb-query,Mongodb,Mongodb Query,我有一个Mongo文档,其中有一个项目列表。这些项目中的每一项都有一些与之关联的状态 我想使用$elemMatch返回状态符合特定条件的文档 考虑以下文档。它代表一个订单,订单中的每个项目都不同(它们代表眼镜): { “_id”:ObjectId(“5335DCD688A4F21DD77657C”), “项目”:[ { “镜头类型”:“标准镜头索引”, “地位”:{} }, { “镜头类型”:“无镜头”, “地位”:{ “已装运”:真 } }, { “镜头类型”:“RX\U太阳镜头”, “地

我有一个Mongo文档,其中有一个项目列表。这些项目中的每一项都有一些与之关联的状态

我想使用
$elemMatch
返回状态符合特定条件的文档

考虑以下文档。它代表一个订单,订单中的每个项目都不同(它们代表眼镜):

{
“_id”:ObjectId(“5335DCD688A4F21DD77657C”),
“项目”:[
{
“镜头类型”:“标准镜头索引”,
“地位”:{}
}, 
{
“镜头类型”:“无镜头”,
“地位”:{
“已装运”:真
}
}, 
{
“镜头类型”:“RX\U太阳镜头”,
“地位”:{
“从实验室收到”是真的,
“送到实验室”是真的,
“已装运”:真
}
}
]
}
我想查找所有“未发货”的项目,即,
items.status.shipped
不存在。我想找到所有准备发货的物品

但是,如果项目有一个处方镜片-<代码> LysSype 是<代码>标准>透镜> <代码>或<代码> RxjSunOxLys——那么,我只认为它是从实验室“代码>项目”收到的。 我的查询不应返回上述文档。这是因为其中两个项目已发货,另一个项目已取消发货,但尚未从实验室收到

但是,我的查询确实返回了此文档

我的问题是:

{
“$and”:[
{
“项目”:{
“$elemMatch”:{
“镜头类型”:{
“$in”:[
“标准折射率透镜”,
“RX_SUN_镜头”
]
},
“status.received_from_lab”:{“$exists”:true}
}
}
},
{
“项目”:{
“$elemMatch”:{
“status.shipped”:{“$exists”:false}
}
}
}
]
}

我的查询中的逻辑错误是什么?我应该使用什么构造来代替?我是否需要在客户端执行这种过滤?

逻辑的问题是,给定文档时,带有“标准索引镜头”的类型与第二个条件匹配,而与“RX\u SUN\u镜头”匹配的项与第一个条件匹配。因此,由于都为真,因此将返回文档

你没有做的是声明你的“处方”镜片可能有这两种情况。所以写这篇文章最简单的方法可能是:

{
“$and”:[
{
“项目”:{
“$elemMatch”:{
“镜头类型”:{
“$in”:[
“标准折射率透镜”,
“RX_SUN_镜头”
]
},
“status.received_from_lab”:{“$exists”:true}
}
}
},
{
“项目”:{
“$elemMatch”:{
“镜头类型”:{
“$nin”:[
“标准折射率透镜”,
“RX_SUN_镜头”
]
},
“status.shipped”:{“$exists”:false}
}
}
}
]
}
因此,那里的操作员确保在检查“已装运”状态时,不会对“处方”类型执行检查,而只对其他项目执行检查,因此无法对其中一个“处方”进行真值评估


正如我所说的,如果您认为您的逻辑在这个限制中更加复杂,那么还有另一种方法可以做到这一点。因此,您需要一种方法将条件应用于数组中的所有元素。您可以使用以下方法完成此操作:

db.order.aggregate([
//文档级过滤仍然有意义
{“$match”:{
“$and”:[
{
“项目”:{
“$elemMatch”:{
“镜头类型”:{
“$in”:[
“标准折射率透镜”,
“RX_SUN_镜头”
]
},
“status.received_from_lab”:{“$exists”:true}
}
}
},
{
“项目”:{
“$elemMatch”:{
“status.shipped”:{“$exists”:false}
}
}
}
]
}},
//放松去正常化
{“$unwind”:“$items”},
//然后实际地“过滤”每一个未缠绕的文档
{“$match”:{
“$and”:[
{
“项目.镜头类型”:{
“$in”:[
“标准折射率透镜”,
“RX_SUN_镜头”
]
},
“items.status.received_from_lab”:{“$exists”:true}
},
{
“items.status.shipped”:{“$exists”:false}
}
]          
}}
//将找到的任何“元素”的结果分组
{“$组”:{
“\u id”:“$\u id”,
“项目”:{“$push”:“$items”}
}}
])
因此,这基本上是在做了初始操作之后,数组中的文档被“拆分”或通常使用“非规范化”,以便它们现在显示为单个文档本身

然后,附加属性确保没有任何剩余内容与这些条件匹配。或者,您可能希望将逻辑更改为另一种情况。最后,您可以使用将任何结果带回a