mongodb 使用匹配的内部数组项的总计重新Map数组

ut6juiuv  于 2023-03-07  发布在  Go
关注(0)|答案(1)|浏览(115)

我的文档集合如下所示:

[
  {
    "_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"
    }
  }
]

我需要在StartAddress=“A”和End Address=“D”之间规划状态、日期以及航段总价(通过传递起始地址和结束地址找到航段ID,并在legId上使用$gt和$lt)
FYI:至于查找顶级文档,我使用每个文档中的祖先字段来筛选2所需的文档。
抱歉,我没听懂你的话。

o8x7eapl

o8x7eapl1#

剩下的主要是$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应用于此$map"input",但您的问题除了返回"totalPrice"之外没有指示任何内容。
所以其他的数组属性仅仅是在输出中命名的,就像在其他语言实现中使用“map”一样,对于"totalPrice",您显然需要$sum,但是我们需要使用$filter来匹配数组元素,然后使用$map来获取特定的字段"price",以实际提供给$sum
这里$filter的参数是在"cond"中指定的,在"cond"中使用$gte$lte的“逻辑形式”,它们返回参数所期望的布尔结果,然后才保留这些数组成员。扩展了该逻辑条件,确保两个内部参数都需要返回true,以便返回true

相关问题