我最近发现很难找到存储在文档中的对象,其密钥位于同一文档的另一个字段中。
{
list : {
"red" : 397n8,
"blue" : j3847,
"pink" : 8nc48,
"green" : 983c4,
},
result : [
{ "id" : 397n8, value : "anger" },
{ "id" : j3847, value : "water" },
{ "id" : 8nc48, value : "girl" },
{ "id" : 983c4, value : "evil" }
]
}
}
我试图获得'blue'的值,其id为'j3847',值为'water'。
db.docs.find( { result.id : list.blue }, { result.value : 1 } );
# list.blue would return water
# list.pink would return girl
# list.green would return evil
我尝试了很多东西,甚至找到了一篇很棒的文章,介绍了如何使用同一文档中的值来更新值:Update MongoDB field using value of another field我自己做的;没有成功......:/
如何使用其他字段的值找到MongoDB对象?
答案 0 :(得分:3)
您可以使用mongo聚合中的$filter运算符执行此操作。它返回一个数组,其中只包含符合条件的元素:
db.docs.aggregate([
{
$project: {
result: {
$filter: {
input: "$result",
as:"item",
cond: { $eq: ["$list.blue", "$$item.id"]}
}
}
}
}
])
此查询的输出如下所示:
{
"_id" : ObjectId("569415c8299692ceedf86573"),
"result" : [ { "id" : "j3847", "value" : "water" } ]
}
答案 1 :(得分:2)
一种方法是使用$where
运算符但不建议使用它调用完整的集合扫描,无论其他条件可能使用索引选择,还调用每个结果文档的JavaScript解释器,这是将比本机代码慢得多。
话虽如此,使用替代.aggregate()
方法进行此类比较,这绝对是更好的选择:
db.docs.aggregate([
{ "$unwind": "$result" },
{
"$project": {
"result": 1,
"same": { "$eq": [ "$list.blue", "$result.id" ] }
}
},
{ "$match": { "same": true } },
{
"$project": {
"_id": 0,
"value": "$result.value"
}
}
])
当 $unwind
运算符应用于result
数组字段时,它将为应用了展开的结果字段的每个元素生成一条新记录。它基本上使数据变平,然后在随后的 $project
步骤中检查数组的每个成员,以比较两个字段是否相同。
示例输出
{
"result" : [
{
"value" : "water"
}
],
"ok" : 1
}
另一种方法是在一个 $map
中使用 $setDifference
和 $project
运算符您可以避免使用 $unwind
的步骤,这可能会对非常大的集合造成代价,并且在大多数情况下会导致16MB BSON限制约束:
db.docs.aggregate([
{
"$project": {
"result": {
"$setDifference": [
{
"$map": {
"input": "$result",
"as": "r",
"in": {
"$cond": [
{ "$eq": [ "$$r.id", "$list.blue" ] },
"$$r",
false
]
}
}
},
[false]
]
}
}
}
])
示例输出
{
"result" : [
{
"_id" : ObjectId("569412e5a51a6656962af1c7"),
"result" : [
{
"id" : "j3847",
"value" : "water"
}
]
}
],
"ok" : 1
}