使用$ in在MongoDB中查找子文档 [英] Find sub-documents using $in with MongoDB

查看:216
本文介绍了使用$ in在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)
]}
} )

它会返回所有注释。请帮助理解为什么会发生。



预期结果

  { 
_id:ObjectId(56479d9c8510369a4ecea3a9),
comments:[
{
text:55555,
user_id:ObjectId (563e3337e2bf6c431b297d41),
},
{
text:00000,
user_id:ObjectId(563f7c0a8db7963420cd5732),
},
{
text:00001,
user_id:ObjectId(563f7c0a8db7963420cd5732),
}
]
}



update query(hopelessness)



 < code $ db.getCollection('messages')。find(
{'_id':ObjectId(56479d9c8510369a4ecea3a9)},
{'comments.user_id':{$ in:[ 563f2db0e2bf6c431b297d45,563e3337e2bf6c431b297d41]}},
{'comments.user_id':{$ elemMatch:{$ in:[563f2db0e2bf6c431b297d45,563e3337e2bf6c431b297d (''messages')。find(
{'_id':ObjectId(56479d9c8510369a4ecea3a9)} ,
{$ elemMatch:{'user_id':{$ in:[ObjectId(563f2db0e2bf6c431b297d45),ObjectId(563f7c0a8db7963420cd5732)]}}}}

我只返回1条记录,而且我有这些作者的所有记录

$ 和 $ elemMatch 匹配的元素



要在您的投影中包含多个过滤的数组元素,注释数组,您可以使用聚合 >:

  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中的任何一个匹配,或者它不是目前(即因为它在文档的顶层)包含数据,否则删除它。

My task is to find individual authors(comments.user_id) comment on the article (_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"),
        }
    ]
}

My query looks as follows

db.getCollection('messages').find({
  '_id': ObjectId("56479d9c8510369a4ecea3a9"),
  'comments.user_id': {$in : [
    ObjectId("563e3337e2bf6c431b297d41"),
    ObjectId("563f7c0a8db7963420cd5732")
  ]}
})

It returns all comments. Please help to understand why it happens.

Expected Result

{
    "_id" : ObjectId("56479d9c8510369a4ecea3a9"),
    "comments" : [ 
        {
            "text" : "55555",
            "user_id" : ObjectId("563e3337e2bf6c431b297d41"),
        }, 
        {
            "text" : "00000",
            "user_id" : ObjectId("563f7c0a8db7963420cd5732"),
        }, 
        {
            "text" : "00001",
            "user_id" : ObjectId("563f7c0a8db7963420cd5732"),
        }
    ]
}

update query (hopelessness)

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")]}}}}  
    )

I return only 1 record, and I have all the records from these authors

解决方案

As you've seen, the $ and $elemMatch projection operators only include the first matching element.

To include multiple, filtered array elements in your projection of the comment array, your can use aggregate with the $redact operator instead of 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 iterates over each doc like a tree, keeping or trimming the fields of each doc as it's $cond expression dictates.

It gets a bit tricky to wrap your head around $redact, but it's basically saying that if the level's user_id field matches either of the two ObjectIds in your $in, or it's not present (i.e. as it is in the top level of the doc), include the data, otherwise remove it.

这篇关于使用$ in在MongoDB中查找子文档的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆