使用 $in with MongoDB 查找子文档
Find sub-documents using $in with MongoDB
我的任务是找到个别作者(comments.user_id
)评论文章(_id
)
{
"_id" : ObjectId("56479d9c8510369a4ecea3a9"),
"comments" : [
{
"text" : "222",
"user_id" : ObjectId("563f2db0e2bf6c431b297d45"),
},
{
"text" : "333",
"user_id" : ObjectId("563f2db0e2bf6c431b297d45"),
},
{
"text" : "444",
"user_id" : ObjectId("563f2db0e2bf6c431b297d45"),
},
{
"text" : "55555",
"user_id" : ObjectId("563e3337e2bf6c431b297d41"),
},
{
"text" : "00000",
"user_id" : ObjectId("563f7c0a8db7963420cd5732"),
},
{
"text" : "00001",
"user_id" : ObjectId("563f7c0a8db7963420cd5732"),
}
]
}
我的查询如下所示
db.getCollection('messages').find({
'_id': ObjectId("56479d9c8510369a4ecea3a9"),
'comments.user_id': {$in : [
ObjectId("563e3337e2bf6c431b297d41"),
ObjectId("563f7c0a8db7963420cd5732")
]}
})
它return是所有评论。请帮助理解为什么会这样。
预期结果
{
"_id" : ObjectId("56479d9c8510369a4ecea3a9"),
"comments" : [
{
"text" : "55555",
"user_id" : ObjectId("563e3337e2bf6c431b297d41"),
},
{
"text" : "00000",
"user_id" : ObjectId("563f7c0a8db7963420cd5732"),
},
{
"text" : "00001",
"user_id" : ObjectId("563f7c0a8db7963420cd5732"),
}
]
}
更新查询(无奈)
db.getCollection('messages').find(
{'_id': ObjectId("56479d9c8510369a4ecea3a9")},
{'comments.user_id': {$in: ["563f2db0e2bf6c431b297d45", "563e3337e2bf6c431b297d41"]}},
{'comments.user_id': {$elemMatch: {$in: ["563f2db0e2bf6c431b297d45", "563e3337e2bf6c431b297d41"]}}}
)
db.getCollection('messages').find(
{'_id': ObjectId("56479d9c8510369a4ecea3a9")},
{comments: {$elemMatch: {'user_id': {$in : [ObjectId("563f2db0e2bf6c431b297d45"), ObjectId("563f7c0a8db7963420cd5732")]}}}}
)
我return只有1条记录,我有这些作者的所有记录
如您所见,$
和 $elemMatch
投影运算符仅包含 first 匹配元素。
要在 comment
数组的投影中包含多个过滤后的数组元素,您可以将 aggregate
与 $redact
运算符一起使用,而不是 find
:
db.getCollection('test').aggregate([
{$match: {
'_id': ObjectId("56479d9c8510369a4ecea3a9"),
'comments.user_id': {$in : [
ObjectId("563e3337e2bf6c431b297d41"),
ObjectId("563f7c0a8db7963420cd5732")
]},
}},
{$redact: {
$cond: {
if: {
$or: [
{$eq: ['$user_id', ObjectId("563e3337e2bf6c431b297d41")]},
{$eq: ['$user_id', ObjectId("563f7c0a8db7963420cd5732")]},
{$not: '$user_id'}
]
},
then: '$$DESCEND',
else: '$$PRUNE'
}
}}
])
$redact
像树一样遍历每个文档,根据 $cond
表达式指示保留或修剪每个文档的字段。
绕过 $redact
有点棘手,但它基本上是说,如果关卡的 user_id
字段与 $in
中的两个 ObjectId 中的任何一个匹配,或者它不存在(即因为它在文档的顶层),包括数据,否则将其删除。
我的任务是找到个别作者(comments.user_id
)评论文章(_id
)
{
"_id" : ObjectId("56479d9c8510369a4ecea3a9"),
"comments" : [
{
"text" : "222",
"user_id" : ObjectId("563f2db0e2bf6c431b297d45"),
},
{
"text" : "333",
"user_id" : ObjectId("563f2db0e2bf6c431b297d45"),
},
{
"text" : "444",
"user_id" : ObjectId("563f2db0e2bf6c431b297d45"),
},
{
"text" : "55555",
"user_id" : ObjectId("563e3337e2bf6c431b297d41"),
},
{
"text" : "00000",
"user_id" : ObjectId("563f7c0a8db7963420cd5732"),
},
{
"text" : "00001",
"user_id" : ObjectId("563f7c0a8db7963420cd5732"),
}
]
}
我的查询如下所示
db.getCollection('messages').find({
'_id': ObjectId("56479d9c8510369a4ecea3a9"),
'comments.user_id': {$in : [
ObjectId("563e3337e2bf6c431b297d41"),
ObjectId("563f7c0a8db7963420cd5732")
]}
})
它return是所有评论。请帮助理解为什么会这样。
预期结果
{
"_id" : ObjectId("56479d9c8510369a4ecea3a9"),
"comments" : [
{
"text" : "55555",
"user_id" : ObjectId("563e3337e2bf6c431b297d41"),
},
{
"text" : "00000",
"user_id" : ObjectId("563f7c0a8db7963420cd5732"),
},
{
"text" : "00001",
"user_id" : ObjectId("563f7c0a8db7963420cd5732"),
}
]
}
更新查询(无奈)
db.getCollection('messages').find(
{'_id': ObjectId("56479d9c8510369a4ecea3a9")},
{'comments.user_id': {$in: ["563f2db0e2bf6c431b297d45", "563e3337e2bf6c431b297d41"]}},
{'comments.user_id': {$elemMatch: {$in: ["563f2db0e2bf6c431b297d45", "563e3337e2bf6c431b297d41"]}}}
)
db.getCollection('messages').find(
{'_id': ObjectId("56479d9c8510369a4ecea3a9")},
{comments: {$elemMatch: {'user_id': {$in : [ObjectId("563f2db0e2bf6c431b297d45"), ObjectId("563f7c0a8db7963420cd5732")]}}}}
)
我return只有1条记录,我有这些作者的所有记录
如您所见,$
和 $elemMatch
投影运算符仅包含 first 匹配元素。
要在 comment
数组的投影中包含多个过滤后的数组元素,您可以将 aggregate
与 $redact
运算符一起使用,而不是 find
:
db.getCollection('test').aggregate([
{$match: {
'_id': ObjectId("56479d9c8510369a4ecea3a9"),
'comments.user_id': {$in : [
ObjectId("563e3337e2bf6c431b297d41"),
ObjectId("563f7c0a8db7963420cd5732")
]},
}},
{$redact: {
$cond: {
if: {
$or: [
{$eq: ['$user_id', ObjectId("563e3337e2bf6c431b297d41")]},
{$eq: ['$user_id', ObjectId("563f7c0a8db7963420cd5732")]},
{$not: '$user_id'}
]
},
then: '$$DESCEND',
else: '$$PRUNE'
}
}}
])
$redact
像树一样遍历每个文档,根据 $cond
表达式指示保留或修剪每个文档的字段。
绕过 $redact
有点棘手,但它基本上是说,如果关卡的 user_id
字段与 $in
中的两个 ObjectId 中的任何一个匹配,或者它不存在(即因为它在文档的顶层),包括数据,否则将其删除。