使用另一个字段的值查找 MongoDB 对象
Posted
技术标签:
【中文标题】使用另一个字段的值查找 MongoDB 对象【英文标题】:Find MongoDB object using value of another field 【发布时间】:2016-04-16 07:00:14 【问题描述】:我最近发现很难找到存储在文档中的对象,其键位于同一文档的另一个字段中。
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"
]
我正在尝试获取 id 为“j3847”且值为“water”的“blue”的值。
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 对象?
【问题讨论】:
【参考方案1】:一种方法是使用$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
另一种方法是在单个 $project
步骤中使用 $map
和 $setDifference
运算符,您可以避免使用 $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
【讨论】:
您的查询是遍历整个文档集合,还是我们可以使用文档 _id 指定要“聚合”的文档? 如果您想通过_id
或任何其他键过滤进入聚合管道的文档,您可以使用$match
管道运算符。这类似于 MongoDB Collection 的 find()
方法和 SQL 的 WHERE
子句。基本上,这会过滤传递给下一个操作员的数据。管道中可以有多个 $match
运算符。【参考方案2】:
您可以使用 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" ]
【讨论】:
除了符合条件的值之外,是否可以返回其他值? @samland 是的,您可以使用以下语法向projection 添加其他字段:字段:1。或者您可以使用$$ROOT 将整个文档投影到字段中。在投影中它看起来像这样:document: 'ROOT'以上是关于使用另一个字段的值查找 MongoDB 对象的主要内容,如果未能解决你的问题,请参考以下文章
将数组中对象的字段添加到同一数组中对象的另一个字段MongoDB
UpdateOne MongoDB 使用来自另一个字段的值进行推送
使用 EF 和 Linq 通过另一个表字段值的值在表中查找字段