在mongodb中过滤嵌套数组?

时间:2018-06-12 17:16:20

标签: mongodb mongoose mongodb-query aggregation-framework

我有一个看起来像这样的文件:

{
    "_id": {
        "$oid": "5b1586ccf0c56353e89d330b"
    },
    "address": {
        "street": "123 Street",
        "address2": "Address 2",
        "city": "Some City",
        "state": "MI",
        "zip": "12345"
    },
    "subs": [
        {
            "invoices": [
                {
                    "address": {
                        "street": "3061 Pine Ave SW",
                        "city": "Grandville",
                        "state": "AK",
                        "zip": "49418"
                    },
                    "lineItem": [
                        {
                            "images": [
                                {
                                    "_id": {
                                        "$oid": "5b1fca54e6ee1d80c463612d"
                                    },
                                    "name": "1528810066348_RSA Logo.jpeg",
                                    "url": "https....",
                                    "uploadDate": {
                                        "$date": "2018-06-12T13:27:46.931Z"
                                    },
                                    "size": 91819
                                }
                            ],
                            "_id": {
                                "$oid": "5b1fca54e6ee1d80c463612c"
                            },
                            "desc": "2",
                            "amt": 2
                        }
                    ],
                    "_id": {
                        "$oid": "5b1fca54e6ee1d80c463612b"
                    }
                }
            ],
            "_id": {
                "$oid": "5b1fc7f23b595481d4599f58"
            },
            "email": "a@a.com",
            "scope": "Roof",
        },
        {
            "invoices": [
                {
                    "address": {
                        "street": "3061 Pine Ave SW",
                        "city": "Grandville",
                        "state": "AL",
                        "zip": "49418"
                    },
                    "lineItem": [
                        {
                            "images": [
                                {
                                    "_id": {
                                        "$oid": "5b1fca2fe6ee1d80c463612a"
                                    },
                                    "name": "1528810029700_RSA Stamp.png",
                                    "url": "https....",
                                    "uploadDate": {
                                        "$date": "2018-06-12T13:27:10.403Z"
                                    },
                                    "size": 238113
                                }
                            ],
                            "_id": {
                                "$oid": "5b1fca2fe6ee1d80c4636129"
                            },
                            "desc": "1",
                            "amt": 1
                        }
                    ],
                    "_id": {
                        "$oid": "5b1fca2fe6ee1d80c4636128"
                    }
                },
                {
                    "address": {
                        "street": "3061 Pine Ave SW",
                        "city": "Grandville",
                        "state": "AL",
                        "zip": "49418"
                    },
                    "lineItem": [
                        {
                            "images": [
                                {
                                    "_id": {
                                        "$oid": "5b1fd05b0d1f7185e02e9c40"
                                    },
                                    "name": "1528811607099_error page.PNG",
                                    "url": "https....",
                                    "uploadDate": {
                                        "$date": "2018-06-12T13:53:28.080Z"
                                    },
                                    "size": 224772
                                }
                            ],
                            "_id": {
                                "$oid": "5b1fd05b0d1f7185e02e9c3f"
                            },
                            "desc": "3",
                            "amt": 3
                        }
                    ],
                    "_id": {
                        "$oid": "5b1fd05b0d1f7185e02e9c3e"
                    }
                }
            ],
            "_id": {
                "$oid": "5b1fc7f23b595481d4599f55"
            },
            "email": "b@b.com",
            "scope": "Siding",
        }
    ],
    "firstName": "",
    "lastName": "",
}

我的问题是,我希望能够访问特定invoices的特定subs

我是Mongo / Mongoose的新手,所以我可能做错了一些事情,对于我如何接近这个问题,我会对任何答案/批评感到高兴。

- 调整回答 -

Job.aggregate([
    {
        $match: {
          "_id": mongoose.Types.ObjectId(req.body.jobID)
        }
    },
    {
        $unwind: "$subs"
    },
    {
        $match: {
            "subs._id": mongoose.Types.ObjectId(req.body.subID)
        }
    },
    {
        $unwind: "$subs.invoices"
    },
    {
        $match: {
            "subs.invoices._id": mongoose.Types.ObjectId(req.body.invID)
        }
    },
    {
        $project: {
            "_id": 1,
            "subs.invoices": 1
        }
    }
], function(err, job) {
    if (err) throw err;
    res.send(job);
});

1 个答案:

答案 0 :(得分:1)

您可以尝试以下聚合...

这是一个使用$unwind解构数组并使用$group

重建数组的漫长过程
db.collection.aggregate([
  { "$match": { "_id": "1111" } },
  { "$unwind": "$subs" },
  { "$match": { "subs._id": "2222" } },
  { "$unwind": "$subs.invoices" },
  { "$match": { "subs.invoices._id": "3333" } },
  { "$group": {
    "_id": {
      "_id": "$_id",
      "subs": "$subs._id"
    },
    "firstName": { "$first": "$firstName" },
    "lastName": { "$first": "$lastName" },
    "address": { "$first": "$address" },
    "subs": {
      "$first": {
        "_id": "$subs._id",
        "email": "$subs.email",
        "venue": "$subs.venue",
        "scope": "$subs.scope"
      }
    },
    "invoices": { "$push": "$subs.invoices" }
  }},
  { "$group": {
    "_id": "$_id._id",
    "firstName": { "$first": "$firstName" },
    "lastName": { "$first": "$lastName" },
    "address": { "$first": "$address" },
    "subs": {
      "$push": {
        "_id": "$subs._id",
        "email": "$subs.email",
        "venue": "$subs.venue",
        "scope": "$subs.scope",
        "invoices": "$invoices"
      }
    }
  }}
])

或者您可以使用$filter聚合

来执行此操作
db.collection.aggregate([
  { "$match": { "_id": "5b1586ccf0c56353e89d330b" }},
  { "$unwind": "$subs" },
  { "$match": { "subs._id": "5b1fc7f23b595481d4599f58" }},
  { "$project": {
    "address": 1, "firstName": 1, "lastName": 1,
    "subs.type": "$subs._id",
    "subs.status": "$subs.email",
    "subs.code": "$subs.scope",
    "subs.invoices": {
      "$filter": {
        "input": "$subs.invoices",
        "as": "invoice",
        "cond": {
          "$eq": [
            "$$invoice._id",
            "5b1fca54e6ee1d80c463612b"
          ]
        }
      }
    }
  }},
  { "$group": {
    "_id": "$_id",
    "address": { "$first": "$address" },
    "firstName": { "$first": "$firstName" },
    "lastName": { "$first": "$lastName" },
    "subs": { "$push": "$subs" }
  }}
])