Mongodb 能否在单个聚合管道中按id查找多个文档?

Mongodb 能否在单个聚合管道中按id查找多个文档?,mongodb,mongoose,aggregation-framework,Mongodb,Mongoose,Aggregation Framework,我正在编写一个用户详细信息API视图,并希望添加一个is_following标志,以指示经过身份验证的API用户(用户a)是否在跟踪他们正在查看的用户配置文件(用户B) 在请求时,我只有经过身份验证的API用户的\u id。我可以在一次查询中获取经过身份验证的API用户的following字段,然后继续为他们感兴趣的用户进行第二次查询,但我认为在一次聚合中将该工作传递给数据库(如果可能的话)会更有效 假设我对users集合有以下模式: [ { _id: 1,

我正在编写一个用户详细信息API视图,并希望添加一个
is_following
标志,以指示经过身份验证的API用户(用户a)是否在跟踪他们正在查看的用户配置文件(用户B

在请求时,我只有经过身份验证的API用户的
\u id
。我可以在一次查询中获取经过身份验证的API用户的
following
字段,然后继续为他们感兴趣的用户进行第二次查询,但我认为在一次聚合中将该工作传递给数据库(如果可能的话)会更有效

假设我对
users
集合有以下模式:

[
    {
        _id: 1,
        name: 'David',
        following: [2, 3] // David follows Sam and Lucy
    },
    {
        _id: 2,
        name: 'Sam',
        following: [1] // Sam only follows David
    },
    {
        _id: 3,
        name: 'Lucy',
        following: [1, 2] // Lucy follows David and Sam
    },
]
我想知道是否有可能按照我目前的想法编写聚合:

  • 通过
    \u id
  • 后面的
    数组以某种方式存储在聚合管道中,以便以后针对我们希望查看的用户使用
  • 对于不同的用户,通过其
    \u id
    再次匹配用户a有兴趣查看的用户(用户B
  • 使用投影,添加一个新的布尔字段
    is\u following
    ,该字段表示用户B的
    \u id
    是否在我们先前存储的经过身份验证的API用户(用户a)的
    following
    数组中。i、 e登录用户正在跟踪其当前查看的用户配置文件
  • 我不确定的是步骤2和步骤3,我不确定在一个聚合查询中是否可以实现抓取两个具有不同
    $match
    条件的文档的方法

    编辑:添加预期输出

    如果经过身份验证的用户(用户A)是
    \u id
    2,而被查看的用户用户B
    \u id
    1:

    {
        _id: 1,
        name: 'David',
        following: [2, 3],
        is_following: true
    }
    
    如果经过身份验证的用户(用户A)是
    \u id
    2,而被查看的用户,用户B
    \u id
    3:

    {
        _id: 3,
        name: 'Lucy',
        following: [1, 2],
        is_following: false
    }
    

    您的问题不是100%清楚,但您似乎在寻找一个简单的方法,对相同的数据与结果用户进行比较。您可能真的一次只想让单个用户使用它,因此该用户的“选项”通常是这里的“选项”

    除了标准结果之外,它没有太多内容,然后使用与“父级”
    \u id
    进行比较,并将新属性添加到数组中

    理想情况下,使用MongoDB 3.6,您可以应用:

    对于早期版本,只需在中“显式”命名要返回的字段:

    Person.aggregate([
      // { "$match": { "_id": 3 } },
      { "$lookup": {
        "from": Person.collection.name,
        "localField": "following",
        "foreignField": "_id",
        "as": "following"
      }},
      { "$project": {
        "_id": 1,
        "name": 1,
        "following": {
          "$map": {
            "input": "$following",
            "in": {
              "_id": "$$this._id",
              "name": "$$this.name",
              "following": "$$this.following",
              "is_following": { "$setIsSubset": [["$_id"], "$$this.following"] }
            }
          }
        }
      }}
    ])
    
    基本原理是,当每个元素都由您检查时,您可以比较它们自己的
    “followers”
    数组和当前用户的
    \u id
    值。或者应用于这种比较。一个将值与一个数组和另一个“两个”数组进行比较

    或者,在您甚至没有访问权限的地方,您可以
    .populate()
    ,然后以大致相同的方式简单地“重新映射”数组内容:

    let people = await Person.find().lean().populate('following');
    
    people = people.map(p => ({ 
      ...p,
      following: p.following.map(f => ({
        ...f,
        is_following: f.following.some(e => e._id.equals(p._id))
      }))
    }));
    
    使用该方法进行比较。请注意,由于“对象比较”的工作方式,如果不将
    ObjectId
    值重新映射到字符串,则无法在此处应用

    此处的所有表格都会得出相同的结果:

    {
            "_id" : 1,
            "name" : "David",
            "following" : [
                    {
                            "_id" : 2,
                            "name" : "Sam",
                            "following" : [
                                    1
                            ],
                            "is_following" : true
                    },
                    {
                            "_id" : 3,
                            "name" : "Lucy",
                            "following" : [
                                    1,
                                    2
                            ],
                            "is_following" : true
                    }
            ]
    }
    {
            "_id" : 2,
            "name" : "Sam",
            "following" : [
                    {
                            "_id" : 1,
                            "name" : "David",
                            "following" : [
                                    2,
                                    3
                            ],
                            "is_following" : true
                    }
            ]
    }
    {
            "_id" : 3,
            "name" : "Lucy",
            "following" : [
                    {
                            "_id" : 1,
                            "name" : "David",
                            "following" : [
                                    2,
                                    3
                            ],
                            "is_following" : true
                    },
                    {
                            "_id" : 2,
                            "name" : "Sam",
                            "following" : [
                                    1
                            ],
                            "is_following" : false
                    }
            ]
    }
    

    不太清楚你在问什么。也许您应该通过演示来展示基于所提供的数据样本(或当前数据,如果您认为它仍然适用),您期望得到什么样的结果。有些事情看起来是这样的,但是显示您对请求的预期结果会使它更加清晰。另外,请不要使用类似于
    ObjectId(“1”)
    的东西,这是无效的数据,无法由试图在演示中解决问题的人使用。要么只显示一个真实的
    ObjectId
    值,要么只使用其他有效的值。例如
    \u id:1
    。@NeilLunn关于ObjectId的观点很好。我添加了两个期望输出的示例,希望能让问题更容易理解。因此,我对您的期望输出有点困惑,因为它似乎是相反的。您认为这些结果属于哪个用户(A或B)?只要看最后一个,3跟在1和2后面,因此1是3的跟随者,2不是。你不想让每个潜在的追随者都有
    is\u following
    ,看看他们是否在跟踪“家长”用户吗?还是不?这看起来很奇怪,你给出的输出是3,而这个人实际上在后面跟着另一个人。不是“其他人”在跟踪他们,只是给你一个答案。看看它,如果你真的认为这个过程有什么不对的地方,那么告诉我。据我所知,你所问的逻辑模式是,跟随者也在跟随用户,这就是结果所显示的。@NeilLunn感谢你的回答,并为困惑感到抱歉!集合中的每个用户都拥有他们跟踪的用户,而不是跟踪他们的用户。我试图确定被请求的用户以及最终的输出(用户B)是否被认证的API用户(用户A)跟踪。用户B很可能会跟随用户A,但只有当用户A跟随用户B时,
    is\u following
    字段才应设置为true,因为该字段是从经过身份验证的用户的角度来看的。“我在跟踪这个人吗?”,而不是“他们在跟踪我吗?”希望这有助于澄清问题:)
    {
            "_id" : 1,
            "name" : "David",
            "following" : [
                    {
                            "_id" : 2,
                            "name" : "Sam",
                            "following" : [
                                    1
                            ],
                            "is_following" : true
                    },
                    {
                            "_id" : 3,
                            "name" : "Lucy",
                            "following" : [
                                    1,
                                    2
                            ],
                            "is_following" : true
                    }
            ]
    }
    {
            "_id" : 2,
            "name" : "Sam",
            "following" : [
                    {
                            "_id" : 1,
                            "name" : "David",
                            "following" : [
                                    2,
                                    3
                            ],
                            "is_following" : true
                    }
            ]
    }
    {
            "_id" : 3,
            "name" : "Lucy",
            "following" : [
                    {
                            "_id" : 1,
                            "name" : "David",
                            "following" : [
                                    2,
                                    3
                            ],
                            "is_following" : true
                    },
                    {
                            "_id" : 2,
                            "name" : "Sam",
                            "following" : [
                                    1
                            ],
                            "is_following" : false
                    }
            ]
    }