如果字段不存在,则更新 MongoDB 文档
Updating a MongoDB document if field doesn't exist
每当我使用新字段更新 insert_one
时,我必须始终删除集合中的旧帖子。我知道有使用 update_many
更新此类字段的手动方法,但我知道它效率低下。
例如:
posts.insert_one({
"id": random.randint(1,10000)
"value1": "value1",
"value2": "value2"
})
我使用下面的代码来检查文档是否存在。 这对一个字段有何作用?
if posts.find({'id': 12312}).count() > 0:
我知道我可以轻松覆盖以前的数据,但我知道人们不会喜欢每隔一个月就擦除一次数据。
有没有办法将字段添加到 Python 中的文档?
How would this work for a field?
您可以使用$exists
检查文档中是否存在某个字段。
在你的情况下,你可以将它与 find
结合起来
find({ 'id':1, "fieldToCheck":{$exists:"true"}})
它将 return 文档,如果它存在 id = 1, fieldToCheck is present in doc with id = 1
您可以跳过 id=1
,在这种情况下,它将 return 所有 fieldToCheck
存在的文档
Is there a way to add the field to a document in Python?
您可以将 update
与新字段一起使用,如果存在则将更新,否则将插入。
update({"_id":1}, {field:"x"})
如果 field
存在,它将设置为 x
否则它将添加 field:x
提防update options like multi, upsert
是的,您可以使用 mongoDB shell 中的更新命令来做到这一点。检查 here
这是要使用的命令...
db.collection.update({},{$set : {"newfield":1}},false,true)
以上将适用于 mongoDB shell。如果不存在,它将在所有文档中添加新字段。
如果要使用Python,请使用pymongo。
对于 python,以下命令应该有效
db.collection.update({},{"$set" : {"newfield":1}},False, True)
感谢 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
每当我使用新字段更新 insert_one
时,我必须始终删除集合中的旧帖子。我知道有使用 update_many
更新此类字段的手动方法,但我知道它效率低下。
例如:
posts.insert_one({
"id": random.randint(1,10000)
"value1": "value1",
"value2": "value2"
})
我使用下面的代码来检查文档是否存在。 这对一个字段有何作用?
if posts.find({'id': 12312}).count() > 0:
我知道我可以轻松覆盖以前的数据,但我知道人们不会喜欢每隔一个月就擦除一次数据。
有没有办法将字段添加到 Python 中的文档?
How would this work for a field?
您可以使用$exists
检查文档中是否存在某个字段。
在你的情况下,你可以将它与 find
结合起来find({ 'id':1, "fieldToCheck":{$exists:"true"}})
它将 return 文档,如果它存在 id = 1, fieldToCheck is present in doc with id = 1
您可以跳过 id=1
,在这种情况下,它将 return 所有 fieldToCheck
存在的文档
Is there a way to add the field to a document in Python?
您可以将 update
与新字段一起使用,如果存在则将更新,否则将插入。
update({"_id":1}, {field:"x"})
如果 field
存在,它将设置为 x
否则它将添加 field:x
提防update options like multi, upsert
是的,您可以使用 mongoDB shell 中的更新命令来做到这一点。检查 here
这是要使用的命令...
db.collection.update({},{$set : {"newfield":1}},false,true)
以上将适用于 mongoDB shell。如果不存在,它将在所有文档中添加新字段。
如果要使用Python,请使用pymongo。
对于 python,以下命令应该有效
db.collection.update({},{"$set" : {"newfield":1}},False, True)
感谢 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