【问题标题】:Join a collection to an existing aggregate query mongodb将集合加入到现有的聚合查询 mongodb
【发布时间】:2019-08-31 17:12:12
【问题描述】:

我的 mongodb 数据库中有以下集合结构。

订单

[  
   {  
      "_id":"order_abcd",
      "name":"Order 1"
   },
   {  
      "_id":"order_defg",
      "name":"Order 2"
   }
]

会话

{  
   "_id":"session_abcd"
   "orders": [ ObjectId("order_abcd"), ObjectId("order_defg") ]
}

交易

{  
   "_id":"transaction_abcd"
   "id_session" : ObjectId("session_abcd")
}

我想要实现的是一个与此类似的数据集

[  
   {  
      "_id":"order_abcd",
      "name":"Order 1",
      "transaction":"transaction_abcd"
   },
   {  
      "_id":"order_defg",
      "name":"Order 2",
      "transaction":"transaction_abcd"
   }
]

除了将用于过滤订单的start dateend date 之外,我没有任何输入数据,该查询主要用于报告目的,因此实际上我正在尝试生成一个查询以获取所有订单在给定的时间段之间,并将每个订单的交易 ID 附加到它。

【问题讨论】:

    标签: node.js mongodb express mongodb-query


    【解决方案1】:

    我们可以在每个阶段使用一对$lookup(类似于在SQL 中连接2 个表)和$unwind,最终$project 得到所需的键值对。

    db.Session.aggregate([
      {
        $lookup: {
          from: "Transactions",
          localField: "_id",
          foreignField: "id_session",
          as: "transaction_info"
        }
      },
      { $unwind: "$transaction_info" },
      {
        $lookup: {
          from: "Orders",
          localField: "orders",
          foreignField: "_id",
          as: "order_info"
        }
      },
      { $unwind: "$order_info" },
      {$project:{
        _id:"$order_info._id",
        name:"$order_info.name",
        transaction:"$transaction_info._id"
      }}
    ]).pretty();
    

    给出输出:

    {
        "_id" : "order_abcd",
        "name" : "Order 1",
        "transaction" : "transaction_abcd"
    },
    {
        "_id" : "order_defg",
        "name" : "Order 2",
        "transaction" : "transaction_abcd"
    }
    

    展开阶段用于展开查找,然后在最终项目阶段挑选字段。

    ++更新++

    另一个可能有助于减少第二阶段查找记录的选项,因为$match 日期为Orders 可用于传递过滤后的文档以供下一阶段使用。

    db.Session.aggregate([
      {
        $lookup: {
          from: "Orders",
          localField: "orders",
          foreignField: "_id",
          as: "order_info"
        }
      },
      { $unwind: "$order_info" },
      {
        $match: {} //filter on "order_info.property" (i:e; date,name,id)
      },
      {
        $lookup: {
          from: "Transactions",
          localField: "_id",
          foreignField: "id_session",
          as: "transaction_info"
        }
      },
      { $unwind: "$transaction_info" },
      {
        $project: {
          _id: "$order_info._id",
          name: "$order_info.name",
          transaction: "$transaction_info._id"
        }
      }
    ]).pretty();
    

    【讨论】:

    • 这可行,但看起来这将是一项艰巨的任务,因为 mongo 必须遍历所有 session 集合,然后将它们与各自的 transaction 文档一起加入,然后才能可能匹配过滤器orders。有没有办法在管道的早期运行匹配以减少 mongo 必须执行查找的文档数量?
    • @JudeFernandes 我不确定这会有多大帮助,除非我们可以对其进行基准测试,因为我们在 TransactionsSessions 上没有真正的过滤器,其他方式可能会加入收藏Session->Order 然后有一个$matchOrders 按你提到的日期,然后$lookupTransactions
    • 谢谢,这似乎可行,我会再等一会儿,看看是否还有其他答案,否则将您的答案标记为正确的。
    猜你喜欢
    • 1970-01-01
    • 2012-05-19
    • 2023-03-28
    • 2019-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-27
    • 1970-01-01
    相关资源
    最近更新 更多