从 $in 查询中返回匹配的元素
Returning the matched element from a $in query
我有几个文档遵循这种结构:
{
"queue-type": <integer>,
"participants": [{
"id": <integer>,
"level": <level>,
"flags": <integer>
}]
}
participants.id
上有一个多键索引。
在代码中,有一个查找查询,如下所示:db.queues.find({"participants.id": {"$in": [2, 3, 4]}})
,结果如下:
{"queue-type": 1, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]}
{"queue-type": 25, "participants": [{"id": 5, "level": 10, "flags":4},{"id": 15, "level": 10, "flags":8},{"id": 4, "level": 10, "flags":8}]}
有没有办法同时检索用于匹配查询的元素?类似于:
{"queue-type": 1, "_matched": 2, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]}
{"queue-type": 25, "_matched": 4, "participants": [{"id": 5, "level": 10, "flags":4},{"id": 15, "level": 10, "flags":8},{"id": 4, "level": 10, "flags":8}]}
PS:我试图避免遍历 [2, 3, 4]
和 participants
数组,因为它们更大。
例子:
队列
{"queue-type": 1, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]}
{"queue-type": 2, "participants": [{"id": 3, "level": 10, "flags":0}]}
{"queue-type": 3, "participants": [{"id": 4, "level": 10, "flags":4},{"id": 5, "level": 10, "flags":8}]}
{"queue-type": 4, "participants": [{"id": 7, "level": 10, "flags":4},{"id": 8, "level": 10, "flags":8},{"id": 9, "level": 10, "flags":8}]}
我要检索的结果:
db.queues.find({"participants.id": {"$in": [2]}});
{"queue-type": 1, "_matched": 2, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]}
请注意“_matched”元素与搜索查询中给出的 'participant.id' 相同
另一个例子:
db.queues.find({"participants.id": {"$in": [2, 3, 6]}});
{"queue-type": 1, "_matched": 2, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]}
{"queue-type": 2, "_matched": 3, "participants": [{"id": 3, "level": 10, "flags":0}]}
多个匹配示例:
db.queues.find({"participants.id": {"$in": [1, 2, 3]}});
{"queue-type": 1, "_matched": 1, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]}
{"queue-type": 1, "_matched": 2, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]}
{"queue-type": 2, "_matched": 3, "participants": [{"id": 3, "level": 10, "flags":0}]}
一个不好的解决方案是简单地复制 'participants' 数据 ('participants-cpy') 然后 运行:
db.queues.find({"participants-cpy.id": {"$in": [2]}}, {"participants-cpy.$":1, "participants":1, "_id": 1, "queue-type":1})
可用于检索用于 'match' 查询的元素,但这会生成重复数据 - 这非常糟糕 :p
常规 find
query will not work here. You need to use the aggregation framework. In your pipeline you need to select only those documents that match your query criteria using the $match
管道操作员。
管道中的下一个也是最后一个阶段是 $project
阶段,您可以在该阶段将新字段“_matched”添加到文档中。如果您考虑一下,您会意识到新字段只不过是一个数组,其中包含出现在 "partcipantsId" array/list 和 [=28] 中的所有 "id" 中的元素=] 文档中的字段。
要获得该值,您只需使用 $map
and the $setIntersection
运算符对来自 "participants" 的 participantsId 数组和 "id" 的数组执行集合交集操作。请注意,结果数组仅包含唯一条目,因为 $setIntersection
过滤掉重复项。
participantsId = [1, 2, 3]
db.queues.aggregate([
{ "$match": { "participants.id": { "$in": participantsId } } },
{ "$project": {
"_matched": {
"$setIntersection": [
{ "$map": {
"input": "$participants",
"as": "p",
"in": "$$p.id"
}},
participantsId
]
},
"queue-type": 1,
"participants": 1
}}
])
我有几个文档遵循这种结构:
{
"queue-type": <integer>,
"participants": [{
"id": <integer>,
"level": <level>,
"flags": <integer>
}]
}
participants.id
上有一个多键索引。
在代码中,有一个查找查询,如下所示:db.queues.find({"participants.id": {"$in": [2, 3, 4]}})
,结果如下:
{"queue-type": 1, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]}
{"queue-type": 25, "participants": [{"id": 5, "level": 10, "flags":4},{"id": 15, "level": 10, "flags":8},{"id": 4, "level": 10, "flags":8}]}
有没有办法同时检索用于匹配查询的元素?类似于:
{"queue-type": 1, "_matched": 2, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]}
{"queue-type": 25, "_matched": 4, "participants": [{"id": 5, "level": 10, "flags":4},{"id": 15, "level": 10, "flags":8},{"id": 4, "level": 10, "flags":8}]}
PS:我试图避免遍历 [2, 3, 4]
和 participants
数组,因为它们更大。
例子: 队列
{"queue-type": 1, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]}
{"queue-type": 2, "participants": [{"id": 3, "level": 10, "flags":0}]}
{"queue-type": 3, "participants": [{"id": 4, "level": 10, "flags":4},{"id": 5, "level": 10, "flags":8}]}
{"queue-type": 4, "participants": [{"id": 7, "level": 10, "flags":4},{"id": 8, "level": 10, "flags":8},{"id": 9, "level": 10, "flags":8}]}
我要检索的结果:
db.queues.find({"participants.id": {"$in": [2]}});
{"queue-type": 1, "_matched": 2, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]}
请注意“_matched”元素与搜索查询中给出的 'participant.id' 相同
另一个例子:
db.queues.find({"participants.id": {"$in": [2, 3, 6]}});
{"queue-type": 1, "_matched": 2, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]}
{"queue-type": 2, "_matched": 3, "participants": [{"id": 3, "level": 10, "flags":0}]}
多个匹配示例:
db.queues.find({"participants.id": {"$in": [1, 2, 3]}});
{"queue-type": 1, "_matched": 1, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]}
{"queue-type": 1, "_matched": 2, "participants": [{"id": 1, "level": 10, "flags":4},{"id": 2, "level": 10, "flags":8}]}
{"queue-type": 2, "_matched": 3, "participants": [{"id": 3, "level": 10, "flags":0}]}
一个不好的解决方案是简单地复制 'participants' 数据 ('participants-cpy') 然后 运行:
db.queues.find({"participants-cpy.id": {"$in": [2]}}, {"participants-cpy.$":1, "participants":1, "_id": 1, "queue-type":1})
可用于检索用于 'match' 查询的元素,但这会生成重复数据 - 这非常糟糕 :p
常规 find
query will not work here. You need to use the aggregation framework. In your pipeline you need to select only those documents that match your query criteria using the $match
管道操作员。
管道中的下一个也是最后一个阶段是 $project
阶段,您可以在该阶段将新字段“_matched”添加到文档中。如果您考虑一下,您会意识到新字段只不过是一个数组,其中包含出现在 "partcipantsId" array/list 和 [=28] 中的所有 "id" 中的元素=] 文档中的字段。
要获得该值,您只需使用 $map
and the $setIntersection
运算符对来自 "participants" 的 participantsId 数组和 "id" 的数组执行集合交集操作。请注意,结果数组仅包含唯一条目,因为 $setIntersection
过滤掉重复项。
participantsId = [1, 2, 3]
db.queues.aggregate([
{ "$match": { "participants.id": { "$in": participantsId } } },
{ "$project": {
"_matched": {
"$setIntersection": [
{ "$map": {
"input": "$participants",
"as": "p",
"in": "$$p.id"
}},
participantsId
]
},
"queue-type": 1,
"participants": 1
}}
])