使用匹配的内部数组项的总计重新映射数组

问题描述 投票:0回答:1

我的文档集如下所示:

[
  {
    "_id": {
      "$oid": "596e004151cc92046c28dd39"
    },
    "routes": [
      {
        "legs": [
          {
            "LegId":0,
            "end_address": "B",
            "start_address": "A",
             "price":123
          },
          {
            "LegId":1,
            "end_address": "C",
            "start_address": "B",
             "price":123

          },
          {
            "LegId":2,
            "end_address": "D",
            "start_address": "C",
             "price":120
          },
          {
            "LegId":3,
            "end_address": "E",
            "start_address": "D",
              "price":125
          }
        ]
      }
    ],
    "status": "OK",
    "Date": {
      "$date": "2017-07-18T12:34:07.781Z"
    }
  },
  {
    "_id": {
      "$oid": "596e007d51cc9231a8117607"
    },
    "routes": [
      {
        "legs": [
          {
            "LegId":0,
            "end_address": "E",
            "start_address": "F",
              "price":300
          },
          {
            "LegId":1,
            "end_address": "D",
            "start_address": "E",
              "price":200
          },
          {
            "LegId":2,
            "end_address": "C",
            "start_address": "D",
              "price":200
          },
          {
            "LegId":3,
            "end_address": "B",
            "start_address": "C",
              "price":200
          }
        ]
      }
    ],
    "status": "OK",
    "Date": {
      "$date": "2017-07-18T12:35:09.121Z"
    }
  }
]

我需要投影 Status、Date 以及 StartAddress="A 和 end Address="D" 之间腿的总价(通过传递起始地址和结束地址找到腿 ID,并使用 $gt 和 $lt legId)

仅供参考:至于查找顶级文档,我在每个文档中使用祖先字段来过滤 2 个所需的文档。

对不起,如果我对语言感到困惑。

arrays mongodb mongodb-query aggregation-framework
1个回答
1
投票

剩下的主要是

$filter
$map
$sum
的应用:

db.collection.aggregate([
  // Still actually query for documents that meet the later filter conditions
  { "$match": {
    "routes": {
      "$elemMatch": {
        "legs": {
          "$elemMatch": {
            "start_address": { "$gte": "A" },
            "end_address": { "$lte": "D" }
          }
        }
      }
    }
  }},
  // Just return the wanted array fields and the sum of the matching inner
  { "$addFields": {
    "routes": {
      "$map": {
        "input": "$routes",
        "as": "r",
        "in": {
          "Status": "$$r.Status",
          "Date": "$$r.Date",
          "totalPrice": {
            "$sum": {
              "$map": {
                "input": {
                  "$filter": {
                    "input": "$$r.legs",
                    "as": "l",
                    "cond": {
                      "$and": [
                        { "$gte": [ "$$l.start_address", "A" ] },
                        { "$lte": [ "$$l.end_address", "D" ] }
                      ]
                    }
                  }
                },
                "as": "l",
                "in": "$$l.price"
              }
            }
          }
        }
      }
    }
  }}
])

为了解释这一点,有几个部分。首先,外部

$map
迭代外部
"routes"
数组并简单地返回所有这些条目。如果我们想在这里“过滤”任何东西,那么我们将类似地应用一个
$filter
到这个
"input"
$map
,但是你的问题除了返回
"totalPrice"
之外没有任何意义。

所以其他数组属性只是在输出中命名,就像任何其他语言实现中的“map”一样。对于

"totalPrice"
,您显然想要
$sum
,但是我们需要使用
$filter
来匹配数组元素,然后使用
$map
来获取特定字段
"price"
来实际喂养
$sum
.

$filter
的参数在
"cond"
中指定,您使用
$gte
$lte
的“逻辑形式”,它们返回参数预期的布尔结果,并且仅然后保留那些数组成员。
$and
通过确保两个内部参数都需要返回
true
来扩展逻辑条件,以便返回
true
.

© www.soinside.com 2019 - 2024. All rights reserved.