在文档数组中查找包含字段的子文档
Posted
技术标签:
【中文标题】在文档数组中查找包含字段的子文档【英文标题】:Looking for sub-documents containing a field in a document's array 【发布时间】:2016-04-23 21:27:03 【问题描述】:假设我有以下persons
集合:
"_id": ObjectId("569d07a38e61973f6aded134"),
"name": "john",
"pets": [
"name": "spot",
"type": "dog",
"special": "spot eye"
,
"name": "bob",
"type": "cat",
]
,
"_id": ObjectId("569d07a38e61973f6aded135"),
"name": "susie",
"pets": [
"name": "fred",
"type": "cat",
]
我如何检索宠物中具有special
字段的人?我希望返回的 pets
数组仅包含带有 special
字段的宠物。
例如,上述集合的预期结果是:
"_id": ObjectId("569d07a38e61973f6aded134"),
"name": "john",
"pets": [
"name": "spot",
"type": "dog",
"special": "spot eye"
]
我希望在一个使用pymongo
的查询中实现这一点,尽管即使只是一个工作的 MongoDB 或猫鼬查询也会很可爱。
我尝试过:
db.persons.find(pets:special:$exists:true);
但它返回了 0 条记录,即使应该有一些。
【问题讨论】:
【参考方案1】:如果数组包含嵌入文档,您可以使用dot notation查询嵌入文档中的特定字段。
如果没有点表示法,您正在查询数组文档以获得完整匹配。
尝试以下查询:
db.persons.find('pets.special':$exists:true);
【讨论】:
谢谢。这确实适用于mongo
终端,但由于某种原因,以下pymongo
查询返回完整数组,包括那些没有special
的数组:mperson.find( "pets.special": "$exists":"true" )
。知道为什么吗?
你需要使用python布尔值True而不是字符串“true”:mperson.find( "pets.special": "$exists": True )【参考方案2】:
您可以使用 aggregation framework 来获得所需的结果。运行以下聚合管道:
db.persons.aggregate([
"$match":
"pets.special": "$exists": true
,
"$project":
"name": 1,
"pets":
"$setDifference": [
"$map":
"input": "$pets",
"as": "el",
"in":
"$cond": [
"$gt": [ "$$el.special", null ] ,
"$$el", false
]
,
[false]
]
])
样本输出
"result" : [
"_id" : ObjectId("569d07a38e61973f6aded134"),
"name" : "john",
"pets" : [
"name" : "spot",
"type" : "dog",
"special" : "spot eye"
]
],
"ok" : 1
产生显着差异的运算符是 $setDifference
和 $map
运算符。 $map
运算符本质上创建了一个新的数组字段,该字段保存值作为数组每个元素的子表达式中的评估逻辑的结果。 $setDifference
运算符然后返回一个集合,其中包含出现在第一个集合中但不在第二个集合中的元素;即相对于第一组执行第二组的相对补充。在这种情况下,它将返回最终的 pets
数组,其中包含与父文档无关的元素,基于 special
属性的存在,基于条件运算符 $cond
评估比较运算符返回的表达式 $gt
。
【讨论】:
以上是关于在文档数组中查找包含字段的子文档的主要内容,如果未能解决你的问题,请参考以下文章
从数组中查找并返回第一个匹配的子文档(Meteor / Mongo)