【问题标题】:Mongo db Query to filter nested array of objects in documentMongodb查询过滤文档中的嵌套对象数组
【发布时间】:2018-08-08 10:18:12
【问题描述】:

我有以下文件

{
    "userid": "5a88389c9108bf1c48a1a6a7",
    "email": "abc@gmail.com",
    "lastName": "abc",
    "firstName": "xyz",
    "__v": 0,
    "friends": [{
        "userid": "5a88398b9108bf1c48a1a6a9",
        "ftype": "SR",
        "status": "ACCEPT",
        "_id": ObjectId("5a9585b401ef0033cc8850c7")
    },
    {
        "userid": "5a88398b9108bf1c48a1a6a91111",
        "ftype": "SR",
        "status": "ACCEPT",
        "_id": ObjectId("5a9585b401ef0033cc8850c71111")
    },
    {
        "userid": "5a8ae0a20df6c13dd81256e0",
        "ftype": "SR",
        "status": "pending",
        "_id": ObjectId("5a9641fbbc9ef809b0f7cb4e")
    }]
},
{
    "userid": "5a88398b9108bf1c48a1a6a9",
    "friends": [{ }],
    "lastName": "123",
    "firstName": "xyz",
    .......
},
{
    "userid": "5a88398b9108bf1c48a1a6a91111",
    "friends": [{ }],
    "lastName": "456",
    "firstName": "xyz",
    ...
}   
  • 第一个查询

这里我想从好友数组中获取用户 ID,它的状态等于“接受”。 即

 [5a88398b9108bf1c48a1a6a9,5a88398b9108bf1c48a1a6a91111] 
  • 第二次查询

之后,我必须对同一个集合进行另一个查询,以获取第一个查询中返回的每个用户 ID 的详细信息。 最终查询将返回[5a88398b9108bf1c48a1a6a9,5a88398b9108bf1c48a1a6a91111] 的详细信息 两个用户 ID 即

[
        {
         userid" : "5a88398b9108bf1c48a1a6a9",
         "lastName" : "123",
         "firstName" : "xyz"
         },
       {
         "userid" : "5a88398b9108bf1c48a1a6a91111",
          "lastName" : "456",
           "firstName" : "xyz"
       }
   ]

到目前为止我已经尝试过

 Users.find ({'_id':5a88389c9108bf1c48a1a6a7,"friends.status":'ACCEPT'}, (error, users) => {})  
   or 


 Users.find ({'_id':5a88389c9108bf1c48a1a6a7, friends: { $elemMatch: { status: 'ACCEPT' } } }, (error, users) => {})

【问题讨论】:

  • AlejandroMontilla :我尝试使用以下 mongooes Query 从集合中获取数据 Users.find ({'userid':5a88389c9108bf1c48a1a6a7, friends: { $elemMatch: { status: 'ACCEPT' } } }, (error, users) => { });
  • 请将find 添加到您的问题中。那find 恢复指定的文档?
  • 您缺少ObjectId("5a88389c9108bf1c48a1a6a7") => Users.find({ _id:ObjectId("5a88389c9108bf1c48a1a6a7" )})。也看看$redact
  • 能否请edit 向我们展示您预期的最终输出?
  • @chridam :非常感谢您为第一个查询所做的努力。它对我来说很好。我想要来自同一文档的所有用户(即 firstQuery 结果)的详细信息。希望你能理解我的查询,谢谢:)

标签: node.js mongodb mongoose mongodb-query aggregation-framework


【解决方案1】:

过滤嵌套元素

const products = await Product.aggregate<ProductDoc>([
    {
      $match: {
        userId: data.id,
      },
    },
    {
      $project: {
        promotions: {
          $filter: {
            input: '$promotions',
            as: 'p',
            cond: {
              $eq: ['$$p.status', PromotionStatus.Started],
            },
          },
        },
        userId: 1,
        name: 1,
        thumbnail: 1,
      },
    },
  ]);

多条件

   cond: {
            $and: [
              {
                $eq: [
                  "$$c.product",
                  "37sd87hjsdj3"
                ]
              },
              {
                $eq: [
                  "$$c.date",
                  "date-jan-4-2022"
                ],
                
              }
            ]
          },

【讨论】:

    【解决方案2】:

    使用聚合框架的 $map$filter 运算符来处理任务。 $filter 将根据状态应等于"ACCESS" 的指定条件过滤好友数组,$map 会将过滤后数组的结果转换为所需的格式。

    对于第二个查询,附加一个 $lookup 管道步骤,该步骤在用户集合上执行自联接以检索与前一个管道中的 id 匹配的文档。

    运行以下聚合操作将生成所需的数组:

    User.aggregate([
        { "$match": { "friends.status": "ACCEPT" } },
        { "$project": {
                "users": {
                    "$map": {
                        "input": {
                            "$filter": {
                                "input": "$friends",
                                "as": "el",
                                "cond": { "$eq": ["$$el.status", "ACCEPT"] }
                            }
                        },
                        "as": "item",
                        "in": "$$item.userid"
                    }
                }
        } },
        { "$lookup": {  
            "from": "users",
            "as": "users",
            "localField": "users",
            "foreignField": "userid"
        } },
    ]).exec((err, results) => {
        if (err) throw err;
        console.log(results[0].users); 
    });
    

    【讨论】:

    • 谢谢@chridam,第一个查询工作正常
    • @AnuragGautam 第二个查询需要$lookup 管道,请检查上面的编辑。
    【解决方案3】:

    我没有测试它。只是一个想法,试一试,让我知道。

     db.Users.aggregate(
           [
            {
               $unwind: "$friends"
            },
            {
              $match:{ "$friends.status": "ACCEPT"}
            },
            {
            $project:{ "FriendUserID":"$friends.userid"}
            },
            { 
              $lookup:{  
                 from:"Users",
                 as: "FriendsUsers",
                 localField: "FriendUserID",
                 foreignField: "userid"
              }
            },
            {
              $project: { FriendsUsers.lastName:1,FriendsUsers.firstName:1 }
            }
           ]
        )
    

    【讨论】:

    • 感谢@krishan 分享您的观点,但不幸的是它不起作用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-09
    • 2019-12-18
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    相关资源
    最近更新 更多