【问题标题】:MongoDB Aggregate combine two lookups?MongoDB Aggregate 结合了两个查找?
【发布时间】:2022-01-22 06:19:11
【问题描述】:

所以我的架构在节点和链接之间拆分。链接集合有像

这样的文档
{src: A, dst:B, value:int}

Nodes 集合有

{name:A, ...other info}

我正在尝试为节点聚合信息,以仅使用一种聚合功能来查找已发送和已接收的值数据。

我的聚合函数看起来像

{
 "$lookup":{
    "from":"links",
    "localField":"name",
    "foreignField":"dst",
    "as":"recv"
   }
},
{
 "$lookup":{
     "from":"links",
     "localField":"name",
     "foreignField":"src",
     "as":"sent"
 }
},

然后我只使用$project 来总结发送/接收数组的值,结果

{name:A, sent_value:x, recv_value:y}

这没问题,但我注意到如果我取消其中一个查找,运行时间会显着减少。我正在寻找一种可能将两种查找组合到管道的一个阶段的方法。 我可以很好地分别为 send 和 recv 发出两个聚合,但我想看看是否可以只使用一个聚合。 谢谢

编辑:示例数据

Nodes: {name: "A"}, {name: "B"},{name: "C"}

Links: {src: "A", dst: "B",value:25}, {src: "A", dst: "C", value:3}, {src: "B",dst: "C", value:19}

我想从一个聚合中得到我上面描述的内容:

{name: "A", sent:28, recv: 0}, {name: "B", sent:19, recv:25}, {name: "C",sent:0,recv:22}

【问题讨论】:

  • 如果您可以分享一些示例数据和预期输出,将会很有帮助。
  • @ray 我在示例数据中添加了我要问的要点。

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

您可以通过一次$lookup 一次获取所有 dst 和 src 数据。然后,使用$reduce对数组进行条件求和。

db.nodes.aggregate([
  {
    "$lookup": {
      "from": "links",
      let: {
        name: "$name"
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $or: [
                {
                  $eq: [
                    "$$name",
                    "$src"
                  ]
                },
                {
                  $eq: [
                    "$$name",
                    "$dst"
                  ]
                }
              ]
            }
          }
        }
      ],
      "as": "linksLookup"
    }
  },
  {
    "$project": {
      name: 1,
      recv: {
        "$reduce": {
          "input": "$linksLookup",
          "initialValue": 0,
          "in": {
            "$add": [
              "$$value",
              {
                "$cond": {
                  "if": {
                    $eq: [
                      "$$this.dst",
                      "$name"
                    ]
                  },
                  "then": "$$this.value",
                  "else": 0
                }
              }
            ]
          }
        }
      },
      sent: {
        "$reduce": {
          "input": "$linksLookup",
          "initialValue": 0,
          "in": {
            "$add": [
              "$$value",
              {
                "$cond": {
                  "if": {
                    $eq: [
                      "$$this.src",
                      "$name"
                    ]
                  },
                  "then": "$$this.value",
                  "else": 0
                }
              }
            ]
          }
        }
      }
    }
  }
])

这是Mongo playground 供您参考。

【讨论】:

  • 感谢游乐场,它帮助我了解您的代码中发生了什么。我有一种预感,我必须在查找中执行相关子查询,但不确定从那里去哪里。
猜你喜欢
  • 2021-02-24
  • 1970-01-01
  • 2020-09-20
  • 2021-09-16
  • 2021-07-25
  • 2020-07-07
  • 2015-12-29
  • 2016-09-27
  • 2020-11-20
相关资源
最近更新 更多