【问题标题】:Updating a MongoDB document if field doesn't exist如果字段不存在,则更新 MongoDB 文档
【发布时间】:2021-04-24 13:59:03
【问题描述】:

每当我使用新字段更新我的insert_one 时,我必须始终删除集合中的旧帖子。我知道有使用 update_many 更新此类字段的手动方法,但我知道它效率低下。

例如:

posts.insert_one({
    "id": random.randint(1,10000)
    "value1": "value1",
    "value2": "value2"
})

我使用以下代码检查文档是否存在。 这对某个领域有什么作用?

if posts.find({'id': 12312}).count() > 0:

我知道我可以轻松覆盖以前的数据,但我知道人们不会喜欢每隔一个月擦除一次他们的数据。

有没有办法在 Python 中将字段添加到文档中?

【问题讨论】:

    标签: python python-3.x mongodb pymongo


    【解决方案1】:

    这对一个领域有什么作用?

    您可以使用$exists检查文档中是否存在字段。

    在您的情况下,您可以将其与 find 结合使用

    find({ 'id':1, "fieldToCheck":{$exists:"true"}})
    

    如果存在id = 1, fieldToCheck is present in doc with id = 1,它将返回文档

    您可以跳过id=1,在这种情况下,它将返回所有存在fieldToCheck 的文档

    有没有办法在 Python 中将字段添加到文档中?

    您可以将update 与新字段一起使用,如果存在则更新,否则将插入。

    update({"_id":1}, {field:"x"})
    

    如果存在field,它将设置为x,否则它将添加field:x

    小心update options like multi, upsert

    【讨论】:

      【解决方案2】:

      是的,您可以在 mongoDB shell 中使用 update 命令来执行此操作。检查here

      这是要使用的命令...

      db.collection.update({},{$set : {"newfield":1}},false,true)
      

      以上将在 mongoDB shell 中工作。如果不存在,它将在所有文档中添加新字段。

      如果你想使用 Python,请使用 pymongo。

      对于python,以下命令应该可以工作

      db.collection.update({},{"$set" : {"newfield":1}},False, True)
      

      【讨论】:

        【解决方案3】:

        感谢 john 的回答,我制作了一个完整的解决方案,可以自动更新文档,而无需运行任务,这意味着您不会更新非活动文档。

        import datetime
        import pymongo
        
        database = pymongo.MongoClient("mongodb://localhost:27017")  # Mongodb connection
        db = database.maindb  # Database
        posts = db.items  # Collection within a database
        
        
        # A schema equivalent function that returns the object
        def user_details(name, dob):
            return {
                "username": name,  # a username/id
                "dob": dob,  # some data
                "level": 0,  # some other data
                "latest_update": datetime.datetime.fromtimestamp(1615640176)
                # Must be kept to ensure you aren't doing it that often
            }
        
        
        # The first schema changed for example after adding a new feature
        def user_details2(name, dob, cake):
            return {
                "username": name,  # a username/id
                "dob": dob,  # Some data
                "level": 0,  # Some other data
                "cake": cake,  # Some new data that isn't in the document
                "latest_update": datetime.datetime.utcnow()  # Must be kept to ensure you aren't doing it that often
            }
        
        
        def check_if_update(find, main_document,
                            collection):  # parameters: What you find a document with, the schema dictionary, then the mongodb collection
            if collection.count_documents(find) > 0:  # How many documents match, only proceed if it exists
        
                fields = {}  # Init a dictionary
        
                for x in collection.find(find):  # You only want one for this to work
                    fields = x
        
                if "latest_update" in fields:  # Just in case it doesn't exist yet
                    last_time = fields["latest_update"]  # Get the time that it was last updated
                    time_diff = datetime.datetime.utcnow() - last_time  # Get the time difference between the utc time now and the time it was last updated
                    if time_diff.total_seconds() < 3600:  # If the total seconds of the difference is smaller than an hour
                        print("return")
                        return
        
                db_schema = main_document  # Better naming
                db_schema["_id"] = 0  # Adds the _id schema_key into the dictionary
        
                if db_schema.keys() != fields:
                    print("in")
        
                    for schema_key, schema_value in db_schema.items():
        
                        if schema_key not in fields.keys():  # Main key for example if cake is added and doesn't exist in db fetched fields
                            collection.update_one(find, {"$set": {schema_key: schema_value}})
        
                        else:  # Everything exists and you want to check for if a dictionary within that dictionary is changed
                            try:
                                sub_dict = dict(schema_value)  # Make the value of it a dictionary
        
                                # It exists in the schema dictionary but not in the db fetched document
                                for key2, value2 in sub_dict.items():
                                    if key2 not in fields[schema_key].keys():
                                        new_value = schema_value
                                        new_value[
                                            key2] = value2  # Adding the key and value from the schema dictionary that was added
                                        collection.update_one(find,
                                                              {"$set": {schema_key: new_value}})
        
                                # It exists in the db fetched document but not in the schema dictionary
                                for key2, value2 in fields[schema_key].items():
                                    if key2 not in sub_dict.keys():
        
                                        new_dict = {}  # Get all values, filter then so that only the schema existent ones are passed back
                                        for item in sub_dict:
                                            if item != key2:
                                                new_dict[item] = sub_dict.get(item)
                                        collection.update_one(find, {"$set": {schema_key: new_dict}})
        
                            except:  # Wasn't a dict
                                pass
        
                    # You removed a value from the schema dictionary and want to update it in the db
                    for key2, value2 in fields.items():
                        if key2 not in db_schema:
                            collection.update_one(find, {"$unset": {key2: 1}})
            else:
                collection.insert_one(main_document)  # Insert it because it doesn't exist yet
        
        
        print("start")
        print(posts.find_one({"username": "john"}))
        
        check_if_update({"username": "john"}, user_details("john", "13/03/2021"), posts)
        
        print("inserted")
        print(posts.find_one({"username": "john"}))
        
        check_if_update({"username": "john"}, user_details2("john", "13/03/2021", "Lemon drizzle"), posts)
        
        print("Results:")
        print(posts.find_one({"username": "john"}))
        

        它可以作为gist使用

        【讨论】:

          猜你喜欢
          • 2019-08-04
          • 1970-01-01
          • 2021-06-03
          • 1970-01-01
          • 1970-01-01
          • 2014-09-09
          • 1970-01-01
          • 1970-01-01
          • 2022-11-18
          相关资源
          最近更新 更多