如果我有以下文件
{
"_id" : ObjectId("54986d5531a011bb5fb8e0ee"),
"owner" : "54948a5d85f7a9527a002917",
"type" : "group",
"deleted" : false,
"participants" : [
{ "_id": "54948a5d85f7a9527a002917", "name": "user1" },
{ "_id": "5491234568f7a9527a002918", "name": "user2" },
{ "_id": "5491234568f7a9527a002918", "name": "user3" },
{ "_id": "1234567aaaa7a9527a002917", "name": "user2" }
]
}
如何获取name ='user2'的所有记录?
我正在尝试跟进:
db.users.find({ _id: ObjectId('54a7103b1a57eee00bc0a9e4') },
{ 'participants.$.name': 'user2') }).pretty()
...我得到以下内容:
error: {
"$err" : "Can't canonicalize query: BadValue Positional projection 'participants.$.name' does not match the query document.",
"code" : 17287
}
答案 0 :(得分:1)
虽然位置运算符($)会为参与者数组提供第一个匹配元素。如果您需要名为user2
的所有参与者,则需要汇总结果。
Match
包含所需_id
的文档。
使用redact运算符仅保留所有子文档
参与者,他们的名字为user2
。
代码:
var search = "user2";
db.users.aggregate([
{$match:{"_id":ObjectId("54986d5531a011bb5fb8e0ee")}},
{$redact:{$cond:[{$eq:[{$ifNull:["$name",search]},search]},
"$$DESCEND",
"$$PRUNE"]}},
{$project:{"participants":1,"_id":0}} // set _id:1, if you need the _id.
])
O / P:
{
"participants" : [
{
"_id" : "5491234568f7a9527a002918",
"name" : "user2"
},
{
"_id" : "1234567aaaa7a9527a002917",
"name" : "user2"
}
]
}
来到您的查询,
db.users.find({ _id: ObjectId('54a7103b1a57eee00bc0a9e4') },
{ 'participants.$.name': 'user2'}).pretty()
位置运算符只能应用于数组,在find函数的查询文档中引用。上述查询文档没有对名为participants
的数组的引用,仅引用_id
字段来匹配文档。因此你得到了错误。
来自docs,
受限制的字段必须出现在查询文档
中
因此,更改查询以在查询文档中包含参与者数组将修复错误。
db.users.find({ "_id":ObjectId('54a7103b1a57eee00bc0a9e4'),
"participants.name": "user2"
},
{"participants.$.name":"user2"}).pretty()
但它只返回与查询文档中的条件匹配的第一个参与者。
来自docs,
在find()方法或findOne()的投影文档中使用$ 当您只需要选中一个特定数组元素时的方法 文档。
O / P:
{
"_id" : ObjectId("54986d5531a011bb5fb8e0ee"),
"participants" : [
{
"_id" : "5491234568f7a9527a002918",
"name" : "user2"
}
]
}