首页 > 解决方案 > 如何使用 $set 和点符号来使用相应的旧元素更新嵌入的数组元素?

问题描述

我在 MongoDb 中有以下文件:

from pymongo import MongoClient
client = MongoClient(host='my_host', port=27017)
database = client.forecast
collection = database.regions
collection.delete_many({})
regions = [
    {
        'id': 'DE',
        'sites': [
            {
                'name': 'paper_factory',
                'energy_consumption': 1000
            },
            {
                'name': 'chair_factory',
                'energy_consumption': 2000
            },
        ]
    },
    {
        'id': 'FR',
        'sites': [
            {
                'name': 'pizza_factory',
                'energy_consumption': 3000
            },
            {
                'name': 'foo_factory',
                'energy_consumption': 4000
            },
        ]
    }
]
collection.insert_many(regions)

现在我想将该属性复制到每个站点sites.energy_consumption的新字段:sites.new_field

set_stage = {
    "$set": {
        "sites.new_field": "$sites.energy_consumption"
    }
}

pipeline = [set_stage]
collection.aggregate(pipeline)

但是,不是复制每个站点的单个值,而是收集所有站点值并将其添加为数组。Intead of 'new_field': [1000, 2000]我想为第一个站点获取'new_field': 1000 :

{
    "_id": ObjectId("61600c11732a5d6b103ba6be"),
    "id": "DE",
    "sites": [
      {
        "name": "paper_factory",
        "energy_consumption": 1000,
        "new_field": [
          1000,
          2000
        ]
      },
      {
        "name": "chair_factory",
        "energy_consumption": 2000,
        "new_field": [
          1000,
          2000
        ]
      }
    ]
  },
  {
    "_id": ObjectId("61600c11732a5d6b103ba6bf"),
    "id": "FR",
    "sites": [
      {
        "name": "pizza_factory",
        "energy_consumption": 3000,
        "new_field": [
          3000,
          4000
        ]
      },
      {
        "name": "foo_factory",
        "energy_consumption": 4000,
        "new_field": [
          3000,
          4000
        ]
      }
    ]
  }

=> 我可以使用什么表达式来仅使用数组的相应条目?

是否有某种当前索引运算符

$sites[<current_index>].energy_consumption

替代点运算符(会提醒我 * 乘法和 .* 元素矩阵乘法之间的区别)?

$sites:energy_consumption

或者这是一个错误?

编辑

我还尝试使用“$”位置运算符,例如

sites.$.new_field

或者

$sites.$.energy_consumption

但后来我得到了错误

FieldPath field names may not start with '$'

有关的:

https://docs.mongodb.com/manual/reference/operator/aggregation/set/#std-label-set-add-field-to-embedded

在 MongoDB 中,如何使用 $set 更新嵌套值/嵌入文档?

标签: mongodbaggregation-frameworkpymongo

解决方案


如果通过选择该字段是数组的成员,则您将选择所有这些字段。

{ar :[{"a" : 1}, {"a" : 2}]}

"$ar.a" = [1 ,2]

此外,您不能将更新运算符与聚合混合使用,您不能使用类似的东西 $sites.$.energy_consumption,如果您正在进行聚合,则必须使用聚合运算符,只有$match可以使用查询运算符的阶段除外。

询问

  • 使用与您的解决方案略有不同的替代解决方案$setField
  • 我想它会更快,但可能差别不大
  • 无需使用 javascript 会更慢
  • 这是 >= MongoDB 5 解决方案,$setField是新运算符

测试代码在这里

aggregate(
[{"$set":
  {"sites":
   {"$map":
    {"input":"$sites",
     "in":
     {"$setField":
      {"field":"new_field",
       "input":"$$this",
       "value":"$$this.energy_consumption"}}}}}}]
)

推荐阅读