Pymongo - 不允许在_id上修改

1 投票
1 回答
1775 浏览
提问于 2025-04-18 07:43

我有一个Mongo数据库的集合需要更新,我正在尝试使用collection.update这个命令,但一直没有成功。

下面是我的代码:

import pymongo
from pymongo import MongoClient
client = MongoClient()
db = client.SensorDB
sensors = db.Sensor

for sensor in sensors.find():
    lat = sensor['location']['latitude']
    lng = sensor['location']['longitude']
    sensor['location'] = {
        "type" : "Feature",
        "geometry" : {
            "type" : "Point",
            "coordinates" : [lat ,lng]
        },
        "properties": {
            "name": sensor['name']
        }
    }

    sensors.update({'webid': sensor['webid']} , {"$set": sensor}, upsert=True)

但是,运行这段代码后,我得到了以下结果:

Traceback (most recent call last):
  File "purgeDB.py", line 21, in <module>
    cameras.update({'webid': sensor['webid']} , {"$set": sensor}, upsert=True)
  File "C:\Anaconda\lib\site-packages\pymongo\collection.py", line 561, in update
    check_keys, self.uuid_subtype), safe)
  File "C:\Anaconda\lib\site-packages\pymongo\mongo_client.py", line 1118, in _send_message
    rv = self.__check_response_to_last_error(response, command)
  File "C:\Anaconda\lib\site-packages\pymongo\mongo_client.py", line 1060, in __check_response_to_last_error
    raise OperationFailure(details["err"], code, result)
pymongo.errors.OperationFailure: Mod on _id not allowed

1 个回答

4

把这一行改成:

for sensor in sensors.find():

改成这样:

for sensor in sensors.find({}, {'_id': 0}):

这样做的目的是让Mongo不返回_id字段,因为你并不需要它,而这个字段在你后面的update()调用中会造成问题,因为你不能“更新”_id


还有一个更好的解决方案(只写需要的数据)

for sensor in sensors.find():
    lat = sensor['location']['latitude']
    lng = sensor['location']['longitude']
    location = {
        "type" : "Feature",
        "geometry" : {
            "type" : "Point",
            "coordinates" : [lat ,lng]
        },
        "properties": {
            "name": sensor['name']
        }
    }

    sensors.update({'webid': sensor['webid']} , {"$set": {'location': location}})

补充: 正如Loïc Faure-Lacroix提到的,你在这种情况下也不需要upsert标志 - 你的代码在这里总是进行更新,而不是插入。

补充2: 在第一个解决方案中,把_id用引号括起来。

撰写回答