如何在具有不同对象顺序的对象数组上使用 $setUnion 来更新文档

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

我有这个文件:

{
  "_id": "65b294740c5693e3deac0cea",
  "name": "Islamic Republic Of Iran",
  "population": 95000000,
  "abb": "IRI",
  "cities": [
    {
      "_id": "65b294740c5693e3deac0cf6",
      "name": "Hamedan",
      "population": 10,
      "abb": "HM"
    },
    {
      "_id": "65b294750c5693e3deac0cf7",
      "name": "Tehran",
      "population": 50,
      "abb": "TH"
    },
    {
      "_id": "65b294750c5693e3deac0cf8",
      "name": "Kerman",
      "population": 12,
      "abb": "KM"
    },
    {
      "_id": "65b294750c5693e3deac0cf9",
      "name": "Esfahan",
      "population": 25,
      "abb": "ES"
    },
    {
      "_id": "65b294750c5693e3deac0cfa",
      "name": "Mashhad",
      "population": 28,
      "abb": "MS"
    }
  ],
}

我想更新文档并通过以下数组在

cities
字段中保存 5 个独特的城市:

[
    {
        _id: "65b294750c5693e3deac0cfa",
        name: "Mashhad",
        abb: "MS",
        population: 28
    },
    {
        _id: "65b294750c5693e3deac0cfb",
        name: "Tabriz",
        abb: "TB",
        population: 27
    }
]

如果你注意的话,这个数组中

abb
population
字段的顺序与第一个数组不同。
我使用此更新管道来更新
cities
字段:

[
  {
    "$set": {
      "cities": {
        "$filter": {
          "input": "$cities",
          "as": "citiesItem",
          "cond": {
            "$ne": [
              "$$citiesItem._id",
              "65b294750c5693e3deac0cf8"
            ]
          }
        }
      }
    }
  },
  {
    "$set": {
      "cities": {
        "$setUnion": [
          "$cities",
          [
            {
              "_id": "65b294750c5693e3deac0cfa",
              "name": "Mashhad",
              "abb": "MS",
              "population": 28
            },
            {
              "_id": "65b294750c5693e3deac0cfb",
              "name": "Tabriz",
              "abb": "TB",
              "population": 27
            }
          ]
        ]
      }
    }
  },
  {
    "$set": {
      "cities": {
        "$sortArray": {
          "input": "$cities",
          "sortBy": {
            "_id": 1
          }
        }
      }
    }
  },
  {
    "$set": {
      "cities": {
        "$slice": [
          "$cities",
          5
        ]
      }
    }
  }
]

我期待这个物体:

{
    "_id": "65b294750c5693e3deac0cf8",
    "name": "Kerman",
    "population": 12,
    "abb": "KM"
}

要擦除的对象:

{
    _id: "65b294750c5693e3deac0cfb",
    name: "Tabriz",
    abb: "TB",
    population: 27
}

被添加到

cities
数组的末尾。

但是由于字段的顺序不同,“马什哈德”市而不是“大不里士”市在

cities
字段的末尾存储了两次,如下所示:

{
  "_id": "65b294740c5693e3deac0cea",
  "name": "Islamic Republic Of Iran",
  "population": 95000000,
  "abb": "IRI",
  "cities": [
    {
      "_id": "65b294740c5693e3deac0cf6",
      "name": "Hamedan",
      "population": 10,
      "abb": "HM"
    },
    {
      "_id": "65b294750c5693e3deac0cf7",
      "name": "Tehran",
      "population": 50,
      "abb": "TH"
    },
    {
      "_id": "65b294750c5693e3deac0cf9",
      "name": "Esfahan",
      "population": 25,
      "abb": "ES"
    },
    {
      "_id": "65b294750c5693e3deac0cfa",
      "name": "Mashhad",
      "population": 28,
      "abb": "MS"
    },
    {
      "_id": "65b294750c5693e3deac0cfa",
      "name": "Mashhad",
      "abb": "MS",
      "population": 28
    }
  ],
}

我什至尝试使用下面的

pipeline
切换字段的顺序:

[
  {
    "$set": {
      "cities": {
        "$filter": {
          "input": "$cities",
          "as": "citiesItem",
          "cond": {
            "$ne": [
              "$$citiesItem._id",
              "65b294750c5693e3deac0cf8"
            ]
          }
        }
      }
    }
  },
  {
    "$set": {
      "cities": {
        "$setUnion": [
          {
            "$project": {
              "cities": {
                "$map": {
                  "input": "$cities",
                  "as": "orderedItemcities",
                  "in": {
                    "_id": "$$orderedItemcities._id",
                    "name": "$$orderedItemcities.name",
                    "population": "$$orderedItemcities.population",
                    "abb": "$$orderedItemcities.abb"
                  }
                }
              }
            }
          },
          [
            {
              "_id": "65b2976346bd44878b4ae02b",
              "name": "Mashhad",
              "abb": "MS",
              "population": 28
            },
            {
              "_id": "65b2976346bd44878b4ae02c",
              "name": "Tabriz",
              "abb": "TB",
              "population": 27
            }
          ]
        ]
      }
    }
  },
  {
    "$set": {
      "cities": {
        "$sortArray": {
          "input": "$cities",
          "sortBy": {
            "_id": 1
          }
        }
      }
    }
  },
  {
    "$set": {
      "cities": {
        "$slice": [
          "$cities",
          5
        ]
      }
    }
  }
]

但是我收到了这个错误:

无效的 $set : : 导致: : 无法识别的表达式 '$project'

如何为此创建合适的管道?
有没有一种方法可以根据对象的一个键唯一地组合 MongoDB 中的两个数组?
例如,我们是否应该根据

_id
键的值来执行此组合?

arrays mongodb aggregation-framework aggregation mongodb-update
1个回答
2
投票

根据您的第二个查询,我修复了什么:

  1. 删除不需要的

    $project
    cities

  2. abb
    字段的位置应先于
    population
    之前。

  3. 根据文档,“Mashhad”

    _id
    应该是“65b294750c5693e3deac0cfa”。

db.collection.update({},
[
  {
    "$set": {
      "cities": {
        "$filter": {
          "input": "$cities",
          "as": "citiesItem",
          "cond": {
            "$ne": [
              "$$citiesItem._id",
              "65b294750c5693e3deac0cf8"
            ]
          }
        }
      }
    }
  },
  {
    "$set": {
      "cities": {
        "$setUnion": [
          {
            "$map": {
              "input": "$cities",
              "as": "orderedItemcities",
              "in": {
                "_id": "$$orderedItemcities._id",
                "name": "$$orderedItemcities.name",
                "abb": "$$orderedItemcities.abb",
                "population": "$$orderedItemcities.population"
              }
            }
          },
          [
            {
              "_id": "65b294750c5693e3deac0cfa",
              "name": "Mashhad",
              "abb": "MS",
              "population": 28
            },
            {
              "_id": "65b2976346bd44878b4ae02c",
              "name": "Tabriz",
              "abb": "TB",
              "population": 27
            }
          ]
        ]
      }
    }
  },
  {
    "$set": {
      "cities": {
        "$sortArray": {
          "input": "$cities",
          "sortBy": {
            "_id": 1
          }
        }
      }
    }
  },
  {
    "$set": {
      "cities": {
        "$slice": [
          "$cities",
          5
        ]
      }
    }
  }
])

演示解决方案1 @ Mongo Playground

如果您正在寻找替代方法来检查当前文档中存在的提供的输入数组中的

_id
并仅在其不存在时添加,您可以使用以下查询:

db.collection.update({},
[
  {
    "$set": {
      "cities": {
        "$filter": {
          "input": "$cities",
          "as": "citiesItem",
          "cond": {
            "$ne": [
              "$$citiesItem._id",
              "65b294750c5693e3deac0cf8"
            ]
          }
        }
      }
    }
  },
  {
    "$set": {
      "cities": {
        $reduce: {
          input: [
            {
              "_id": "65b294750c5693e3deac0cfa",
              "name": "Mashhad",
              "abb": "MS",
              "population": 28
            },
            {
              "_id": "65b294750c5693e3deac0cfb",
              "name": "Tabriz",
              "abb": "TB",
              "population": 27
            }
          ],
          initialValue: "$cities",
          in: {
            $concatArrays: [
              "$$value",
              {
                $ifNull: [
                  {
                    $cond: {
                      if: {
                        $not: {
                          $in: [
                            "$$this._id",
                            "$cities._id"
                          ]
                        }
                      },
                      then: [
                        "$$this"
                      ],
                      else: null
                    }
                  },
                  []
                ]
              }
            ]
          }
        }
      }
    }
  },
  {
    "$set": {
      "cities": {
        "$sortArray": {
          "input": "$cities",
          "sortBy": {
            "_id": 1
          }
        }
      }
    }
  },
  {
    "$set": {
      "cities": {
        "$slice": [
          "$cities",
          5
        ]
      }
    }
  }
])

演示解决方案 2 @ Mongo Playground

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