db.projects.findOne({"_id": "5CmYdmu2Aanva3ZAy"},
{
"responses": {
"$elemMatch": {
"match.nlu": {
"$elemMatch": {
"intent": "intent1",
"$and": [
{
"$or": [
{
"entities.entity": "entity1",
"entities.value": "value1"
},
{
"entities.entity": "entity1",
"entities.value": {
"$exists": false
}
}
]
}
],
"entities.1": {
"$exists": false
}
}
}
}
}
})
在给定的project
中,我需要一个仅包含一个响应的投影,因此$elemMatch
。理想情况下,寻找完全匹配的内容:
{
"entities.entity": "entity1",
"entities.value": "value1"
}
但是如果不存在这样的匹配项,请寻找entities.value
不存在的记录
上面的查询不起作用,因为如果找到未设置entities.value
的项目,它将返回它。如何在Mongo查询中获得此后备逻辑
这是文档的示例
{
"_id": "5CmYdmu2Aanva3ZAy",
"responses": [
{
"match": {
"nlu": [
{
"entities": [],
"intent": "intent1"
}
]
},
"key": "utter_intent1_p3vE6O_XsT"
},
{
"match": {
"nlu": [
{
"entities": [{
"entity": "entity1",
"value": "value1"
}],
"intent": "intent1"
}
]
},
"key": "utter_intent1_p3vE6O_XsT"
},
{
"match": {
"nlu": [
{
"intent": "intent2",
"entities": []
},
{
"intent": "intent1",
"entities": [
{
"entity": "entity1"
}
]
}
]
},
"key": "utter_intent2_Laag5aDZv2"
}
]
}
答案 0 :(得分:1)
要回答这个问题,首先要做的是做您想做的事并不像$elemMatch
投影那样简单,并且需要聚合框架的特殊投影逻辑。这里的第二个主要原则是“嵌套数组是一个真正的坏主意” ,这正是原因:
db.collection.aggregate([
{ "$match": { "_id": "5CmYdmu2Aanva3ZAy" } },
{ "$addFields": {
"responses": {
"$filter": {
"input": {
"$map": {
"input": "$responses",
"in": {
"match": {
"nlu": {
"$filter": {
"input": {
"$map": {
"input": "$$this.match.nlu",
"in": {
"entities": {
"$let": {
"vars": {
"entities": {
"$filter": {
"input": "$$this.entities",
"cond": {
"$and": [
{ "$eq": [ "$$this.entity", "entity1" ] },
{ "$or": [
{ "$eq": [ "$$this.value", "value1" ] },
{ "$ifNull": [ "$$this.value", false ] }
]}
]
}
}
}
},
"in": {
"$cond": {
"if": { "$gt": [{ "$size": "$$entities" }, 1] },
"then": {
"$slice": [
{ "$filter": {
"input": "$$entities",
"cond": { "$eq": [ "$$this.value", "value1" ] }
}},
0
]
},
"else": "$$entities"
}
}
}
},
"intent": "$$this.intent"
}
}
},
"cond": { "$ne": [ "$$this.entities", [] ] }
}
}
},
"key": "$$this.key"
}
}
},
"cond": { "$ne": [ "$$this.match.nlu", [] ] }
}
}
}}
])
会返回:
{
"_id" : "5CmYdmu2Aanva3ZAy",
"responses" : [
{
"match" : {
"nlu" : [
{
"entities" : [
{
"entity" : "entity1",
"value" : "value1"
}
],
"intent" : "intent1"
}
]
},
"key" : "utter_intent1_p3vE6O_XsT"
}
]
}
这是从{嵌套1的嵌套内部数组提取 first 匹配元素(以尽我所能确定的规格)。 }},同时满足entities
和entity
的条件 OR ,其中value
属性不存在。
请注意其他回退,如果 both 条件都意味着返回多个数组元素,则只有出现value
且匹配的第一个匹配项结果返回。
查询深度嵌套的数组需要$map
和$filter
的链式使用,以便遍历那些数组内容并仅返回符合条件的项目。您无法在$elemMatch
投影中指定这些条件,甚至在最近的MongoDB版本中甚至无法以原子方式更新这样的结构,而不会覆盖文档的重要部分或引入更新问题的情况下,并发。
对此的更详细解释是在我对Updating a Nested Array with MongoDB的现有答案中以及在查询方面的Find in Double Nested Array MongoDB上。
请注意,两个响应均显示$elemMatch
作为“查询”运算符的用法,这实际上仅与“文档选择” 有关(因此不适用于{{1} }匹配条件),不能与以前的“ projection”变体或positional $
投影运算符一起使用。
然后建议您“不嵌套数组” ,而选择“ flatter” 数据结构,因为这些答案已经详细讨论了。