【问题标题】:MongoDB/Mongoose how to return a nested subdocument by _idMongoDB / Mongoose如何通过_id返回嵌套子文档
【发布时间】:2020-03-14 06:07:57
【问题描述】:

这里是 MongoDB 新手。

我有一个如下所示的“客户”文档:

{
  name: "myClient",
  products: [{
    name: "myProduct1",
    environments: [{
        name: "myEnvironment1",
        changeLogs: [
          { "some": "fields21" },
          { "some": "fields22" }
        ]
      },
      {
        name: "myEnvironment2",
        changeLogs: [
          { "some": "fields11" },
          { "some": "fields12" }
        ]
      }
    ]
  },
  {
    name: "myProduct2",
    environments: [{
        name: "myEnv1",
        changeLogs: [
          { "some": "fields1" },
          { "some": "fields2" }
        ]
      },
      {
        name: "myEnv1",
        changeLogs: [
          { "some": "fields3" },
          { "some": "fields4" }
        ]
      }
    ]
  }]
}

所以一个客户有很多products,它有很多environments,它有很多changeLogs。我希望返回给定环境的changeLogs 列表,只有environment._id 继续。

我可以使用这个_id 找到正确的client 文档:

db.clients.find({'products.environments._id': ObjectId("5a1bf4b410842200043d56ff")})

但这会返回整个client 文档。我想要的是从环境中返回 changeLogs 数组 _id: ObjectId("5a1bf4b410842200043d56ff")

假设我有第一个 environment 和第一个 product_id,我想要的输出如下:

[
  { "some": "fields21" },
  { "some": "fields22" }
]

您建议我使用什么查询来实现此目的?

非常感谢您的帮助。到目前为止的文档只是令人困惑,但我相信我最终会到达那里!

【问题讨论】:

    标签: mongodb mongoose nested-documents


    【解决方案1】:

    这里的想法是$unwind products 数组,以便在_id 上的$match 之后将其环境作为输入提供给$filter

    (假设环境 _id 为 1)

    db.collection.aggregate([
      {
        $unwind: "$products"
      },
      {
        $match: {
          "products.environments._id": 1
        }
      },
      {
        $project: {
          "logsArray": {
            $filter: {
              input: "$products.environments",
              as: "env",
              cond: {
                $eq: [
                  "$$env._id",
                  1
                ]
              }
            }
          }
        }
      },
      {
        $unwind: "$logsArray"
      }
    ])
    

    O/P 应该是这样的:

    [
      {
        "_id": ObjectId("5a934e000102030405000000"),
        "logsArray": {
          "changeLogs": [
            {
              "some": "fields21"
            },
            {
              "some": "fields22"
            }
          ],
          "id": 1,
          "name": "myEnvironment1"
        }
      }
    ]
    

    注意:注意logsArray 的最后阶段$unwind,我认为这与输出结果相当。否则,如果没有它,结果也是可以接受的(如果您同意,可以删除它)。

    【讨论】:

    • 我投了赞成票,因为您的解释帮助我理解了如何得出正确的答案,谢谢!但是,您的 $project 和关注 $unwind 似乎没有结果。
    • @FelixFortis 不知道为什么你最终没有结果。请检查plyaground link,其中查询确实从问题中的样本集中获得了所需的结果。
    【解决方案2】:

    这只是进行聚合查询的另一种方式。这样就得到了想要的结果。

    注意,我使用的是您提供的示例文档中“环境”的“名称”字段。 “name”可以根据需要替换为“id”。

    var ENV = "myEnvironment1";
    
    db.env.aggregate( [
      { $match: { 
      { $unwind: "$products" },
      { $unwind: "$products.environments" },
      { $match: { "products.environments.name": ENV} },
      { $project: { _id: 0, changeLogs: "$products.environments.changeLogs" } },
    ] )
    

    结果:

    { "changeLogs" : [ { "some" : "fields21" }, { "some" : "fields22" } ] }
    

    如果变量ENV的值改变了,那么结果也会相应地改变;例如:ENV = "myEnv1";

    { "changeLogs" : [ { "some" : "fields1" }, { "some" : "fields2" } ] }
    { "changeLogs" : [ { "some" : "fields3" }, { "some" : "fields4" } ] }
    

    【讨论】:

    • 你的代码看起来很像我最终想出的那个,但是给了我语法错误。我已经投票了,谢谢!。
    【解决方案3】:
    db.clients.aggregate([
      {
        $unwind: "$products"
      },
      {
        $unwind: "$products.environments" 
      },
      {
        $match: { "products.environments._id": ObjectId("5a1bf4b410842200043fffff") }
      },
      {
        $project: { _id: 0, changeLogs: "$products.environments.changeLogs" }
      }
    ]).pretty()
    

    结果:

    {
      "changeLogs": [
        { "some": "fields21" },
        { "some": "fields22" }
      ]
    }
    

    对于那些发现代码令人困惑的人,我发现一次只添加一个聚合方法,查看结果,然后将下一个方法添加到管道中非常有用。管道完成后,我还尝试删除中间步骤,看看是否可以用更少的管道获得相同的结果。

    【讨论】:

      猜你喜欢
      • 2017-04-01
      • 2017-04-02
      • 1970-01-01
      • 2020-12-31
      • 2021-03-26
      • 2020-09-18
      • 1970-01-01
      • 2018-02-27
      • 2020-05-02
      相关资源
      最近更新 更多