gpt4 book ai didi

mongodb - Mongo 查询仅返回子文档的一个子集

转载 作者:可可西里 更新时间:2023-11-01 09:57:51 25 4
gpt4 key购买 nike

使用 Mongo 文档中的示例:

{ _id: 1, results: [ { product: "abc", score: 10 }, { product: "xyz", score: 5 } ] }
{ _id: 2, results: [ { product: "abc", score: 8 }, { product: "xyz", score: 7 } ] }
{ _id: 3, results: [ { product: "abc", score: 7 }, { product: "xyz", score: 8 } ] }

db.survey.find(
{ id: 12345, results: { $elemMatch: { product: "xyz", score: { $gte: 6 } } } }
)

如何返回调查 12345(无论是否有调查)但返回得分大于 6 的调查?换句话说,我不希望文档从基于子文档的结果中取消资格,我想要文档,但只需要子文档的子集。

最佳答案

您要求的与其说是“查询”,不如说是对每个文档中的数组内容进行过滤。

您使用 .aggregate() 执行此操作和 $project :

db.survey.aggregate([
{ "$project": {
"results": {
"$setDifference": [
{ "$map": {
"input": "$results",
"as": "el",
"in": {
"$cond": [
{ "$and": [
{ "$eq": [ "$$el.product", "xyz" ] },
{ "$gte": [ "$$el.score", 6 ] }
]}
]
}
}},
[false]
]
}
}}
])

因此,不是将结果“限制”到具有与条件匹配的数组成员的文档,而是“过滤”出与条件不匹配的数组成员,但如果需要则返回具有空数组的文档是。

目前最快的方法是使用 $map检查所有元素和$setDifference过滤掉从该检查返回的所有 false 值。可能的缺点是“集合”必须包含唯一元素,所以只要元素本身是唯一的,这就没问题。

future 版本将有一个$filter方法,在结构上类似于$map,但直接去除不匹配的结果,其中as $map 只是返回它们(通过 $cond 和匹配元素或 false )然后更适合。

否则,如果不是唯一的或 MongoDB 服务器版本低于 2.6,您将以非高效的方式使用 $unwind 执行此操作:

db.survey.aggregate([
{ "$unwind": "$results" },
{ "$group": {
"_id": "$_id",
"results": { "$push": "$results" },
"matched": {
"$sum": {
"$cond": [
{ "$and": [
{ "$eq": [ "$results.product", "xyz" ] },
{ "$gte": [ "$results.score", 6 ] }

]},
1,
0
]
}
}
}},
{ "$unwind": "$results" },
{ "$match": {
"$or": [
{
"results.product": "xyz",
"results.score": { "$gte": 6 }
},
{ "matched": 0 }
}},
{ "$group": {
"_id": "$_id",
"results": { "$push": "$results" },
"matched": { "$first": "$matched" }
}},
{ "$project": {
"results": {
"$cond": [
{ "$ne": [ "$matched", 0 ] },
"$results",
[]
]
}
}}
])

这在设计和性能上都非常糟糕。因此,您最好改为在客户端代码中按文档进行过滤。

关于mongodb - Mongo 查询仅返回子文档的一个子集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33717779/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com