MongoDB:如何在嵌套数组中向上插入对象?

MongoDB:如何在嵌套数组中向上插入对象?,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,考虑以下文件: { "countries" : [ { "country" : "France", "cities" : [ { "city" : "Paris", "populat

考虑以下文件:

{
    "countries" : [ 
        {
            "country" : "France",
            "cities" : [ 
                {
                    "city" : "Paris",
                    "population" : 100
                }
            ]
        }, 
        {
            "country" : "England",
            "cities" : [ 
                {
                    "city" : "London",
                    "population" : 100
                }, 
                {
                    "city" : "Liverpool",
                    "population" : 100
                }
            ]
        }
    ]
}
我想添加或更新城市(假设我们有方法
upsert(国家、城市、人口)

我们有3个案例:

  • 国家/地区和城市已存在-这只是一个更新(替换城市对象)
  • 国家存在,但城市不存在-可能只需要
    $push
  • 国家/地区和城市不存在-需要使用包含新城市的大小为
    1
    cities
    数组准备并
    $push
    国家/地区对象
  • 是否可以在一个查询中合并所有这三个操作

    顺便说一下, 我学习了
    $addToSet
    ,但据我所知,它比较了对象的所有键,在我看来,它不起作用,因为我还有
    cities
    ,它是一个数组

    使用ArrayFilter只需更新就可以了:

    q = {"_id":"1"}
    
    update = {
        "$set": {
            "countries.$[i].cities.$[j].population": 200,
    
        }
    } 
    
    options = {
        "arrayFilters": [
            {
                "i.country": "France"
            },
            {
                "j.city": "Paris",
            },
        ],
    }
    
    db.collection.updateOne(q, update, options)
    

    常规更新查询不会插入嵌套数组,我建议您在客户端执行,或者如果您确实想在单个查询中执行,则可以尝试从MongoDB 4.2开始,在聚合管道中执行这是一个漫长的过程

    • $map
      迭代数组循环
    • $mergeObjects
      将当前对象与更新的字段合并
    • $cond
      检查是否存在其他条件
    • $concatarray
      到concat2阵列

    尝试使用@KunalMukherjee更新嵌套文档,实际上我也了解了这一点,但我不确定如何处理
    国家的这三种情况
    文档中是集合名还是键名?@turivishal,这是一个键。整个JSON都是一个文档
    
    var country = "France";
    var city = {
      city: "Paris",
      population: 100
    };
    
    db.collection.update({},
     [{
        $set: {
          countries: {
            $cond: [
              { $in: [country, "$countries.country"] },
              {
                $map: {
                  input: "$countries",
                  in: {
                    $cond: [
                      { $eq: [country, "$$this.country"] },
                      {
                        $mergeObjects: [
                          "$$this",
                          {
                            $cond: [
                              { $in: [city.city, "$$this.cities.city"] },
                              {
                                cities: {
                                  $map: {
                                    input: "$$this.cities",
                                    in: {
                                      $cond: [
                                        { $eq: [city.city, "$$this.city"] },
                                        city,
                                        "$$this"
                                      ]
                                    }
                                  }
                                }
                              },
                              {
                                cities: {
                                  $concatArrays: ["$$this.cities", [city]]
                                }
                              }
                            ]
                          }
                        ]
                      },
                      "$$this"
                    ]
                  }
                }
              },
              {
                $concatArrays: [
                  "$countries",
                  [
                    {
                      country: country,
                      cities: [city]
                    }
                  ]
                ]
              }
            ]
          }
        }
      }]
    )