MongoDB 聚合合并两个查找?

MongoDB Aggregate combine two lookups?

所以我的架构分为节点和链接。链接集合包含

之类的文档
{src: A, dst:B, value:int}

节点集合有

{name:A, ...other info}

我正在尝试为节点聚合信息,以仅使用一个聚合函数来查找发送值数据与接收值数据。

我的聚合函数看起来像

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

然后我只使用 $project 来总结 sent/recv 数组的值,结果是

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

这工作正常,但我注意到如果我取消其中一个查找,运行时间会显着减少。我正在寻找一种可能将两个查找组合到管道的一个阶段的方法。 我可以很好地分别为 sent 和 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}

您可以做一个 $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供大家参考。