Mongodb 更新一个字段或插入多个字段(如果不存在)

Mongodb 更新一个字段或插入多个字段(如果不存在),mongodb,Mongodb,Upsert功能在更新方法中非常好,但它似乎有一个很大的缺点,我无法找到一个合理的解决方案 问题是,如果找到与查询条件匹配的结果,但没有找到行,我只想更新一个字段,我想插入很多字段 例如,如果find({name:John,姓氏:Connor})返回结果,我只想为他设置新的年龄,比如{age:33},但是如果没有找到结果,我想插入很多字段,比如{name:John,姓氏:Connor,年龄:32岁,角色:指挥官,角色:谨慎,爱好:“杀死终结者”} 有没有一种很好的方法可以在一个查询中实现这一点?

Upsert功能在更新方法中非常好,但它似乎有一个很大的缺点,我无法找到一个合理的解决方案

问题是,如果找到与查询条件匹配的结果,但没有找到行,我只想更新一个字段,我想插入很多字段

例如,如果find({name:John,姓氏:Connor})返回结果,我只想为他设置新的年龄,比如{age:33},但是如果没有找到结果,我想插入很多字段,比如{name:John,姓氏:Connor,年龄:32岁,角色:指挥官,角色:谨慎,爱好:“杀死终结者”}

有没有一种很好的方法可以在一个查询中实现这一点?或者,唯一的解决方案是straighforward one,意思是查找、检查找到了多少结果,并基于它插入或更新


编辑:我做了一个补充,解释了一步到位的能力需求。当有一个工作人员进行查找和更新/插入时,分两步(首先查找,然后插入/更新)进行的解决方案是很好的,但是当有大约1000名工作人员尝试进行查找和更新/插入时,这将失败-因此,数据库中可能有很多John Connors(当前两个工作人员找不到结果,所有工作人员都插入一个新行时)除非我为姓氏对创建一个唯一索引(不知何故)。但我正在寻找不这样做的解决方案。

您可以通过匹配完整文档属性来获得所需的功能,但要更新的属性除外。示例如下:

插入集合中唯一的文档:

db.collection.insert({ name: "John", surname: "Connor", age: 32, role: "commander", character: "cautious", hobby: "kill terminators" })
db.collection.find()

{ "_id" : ObjectId("52fc9a02d342217e6262aa28"), "name" : "John", "surname" : "Connor", "age" : 33, "role" : "commander", "character" : "cautious", "hobby" : "kill terminators" }
{ "_id" : ObjectId("52fc9a5f56641f5e1b883677"), "age" : 33, "character" : "cautious", "hobby" : "kill terminators", "name" : "Robot", "role" : "commander", "surname" : "Connor" }
现在

返回:

{ "_id" : ObjectId("52fc9a02d342217e6262aa28"), "name" : "John", "surname" : "Connor", "age" : 32, "role" : "commander", "character" : "cautious", "hobby" : "kill terminators" }
update语句

db.collection.update({"name" : "John", "surname" : "Connor", "role" : "commander", "character" : "cautious", "hobby" : "kill terminators" },{$set:{age:33}}, { upsert: true })
更新现有文档的属性“年龄”:

{ "_id" : ObjectId("52fc9a02d342217e6262aa28"), "name" : "John", "surname" : "Connor", "age" : 33, "role" : "commander", "character" : "cautious", "hobby" : "kill terminators" }
如果运行完全相同的update语句更改名称(因此,find查询将找不到现有文档):

“Robot Connor”文档将在33岁时创建,您的收藏中会有两个文档:

db.collection.insert({ name: "John", surname: "Connor", age: 32, role: "commander", character: "cautious", hobby: "kill terminators" })
db.collection.find()

{ "_id" : ObjectId("52fc9a02d342217e6262aa28"), "name" : "John", "surname" : "Connor", "age" : 33, "role" : "commander", "character" : "cautious", "hobby" : "kill terminators" }
{ "_id" : ObjectId("52fc9a5f56641f5e1b883677"), "age" : 33, "character" : "cautious", "hobby" : "kill terminators", "name" : "Robot", "role" : "commander", "surname" : "Connor" }

注意:我不认为update查询参数上的额外属性对性能有影响。

您可以通过匹配完整文档属性来获得所需的功能,但要更新的属性除外。示例如下:

插入集合中唯一的文档:

db.collection.insert({ name: "John", surname: "Connor", age: 32, role: "commander", character: "cautious", hobby: "kill terminators" })
db.collection.find()

{ "_id" : ObjectId("52fc9a02d342217e6262aa28"), "name" : "John", "surname" : "Connor", "age" : 33, "role" : "commander", "character" : "cautious", "hobby" : "kill terminators" }
{ "_id" : ObjectId("52fc9a5f56641f5e1b883677"), "age" : 33, "character" : "cautious", "hobby" : "kill terminators", "name" : "Robot", "role" : "commander", "surname" : "Connor" }
现在

返回:

{ "_id" : ObjectId("52fc9a02d342217e6262aa28"), "name" : "John", "surname" : "Connor", "age" : 32, "role" : "commander", "character" : "cautious", "hobby" : "kill terminators" }
update语句

db.collection.update({"name" : "John", "surname" : "Connor", "role" : "commander", "character" : "cautious", "hobby" : "kill terminators" },{$set:{age:33}}, { upsert: true })
更新现有文档的属性“年龄”:

{ "_id" : ObjectId("52fc9a02d342217e6262aa28"), "name" : "John", "surname" : "Connor", "age" : 33, "role" : "commander", "character" : "cautious", "hobby" : "kill terminators" }
如果运行完全相同的update语句更改名称(因此,find查询将找不到现有文档):

“Robot Connor”文档将在33岁时创建,您的收藏中会有两个文档:

db.collection.insert({ name: "John", surname: "Connor", age: 32, role: "commander", character: "cautious", hobby: "kill terminators" })
db.collection.find()

{ "_id" : ObjectId("52fc9a02d342217e6262aa28"), "name" : "John", "surname" : "Connor", "age" : 33, "role" : "commander", "character" : "cautious", "hobby" : "kill terminators" }
{ "_id" : ObjectId("52fc9a5f56641f5e1b883677"), "age" : 33, "character" : "cautious", "hobby" : "kill terminators", "name" : "Robot", "role" : "commander", "surname" : "Connor" }

注意:我不认为update查询参数上的额外属性对性能有影响。

您需要匹配足够的条件,使用文档中的确切值选择特定文档,然后发送创建文档所需的所有数据(如果文档不存在)。Ad另外,如果文档不存在,则需要指定创建该文档的选项

update( {name: "John", surname: "Connor" }, 
        { $set :
             {name: "John", surname: "Connor", age: 32, terminated: false}},
        { upsert: true })
请确保您也了解使用
upsert
的本质。查询需要依赖于一个唯一的字段,否则您可能会得到多个具有匹配数据的文档

警告为避免多次插入同一文档,请仅使用 upsert:如果查询字段具有唯一索引,则为true

MongoDB不支持根据查询结果有条件地只更新文档部分的方法。有而不是允许:

updateIf(query, updateIfTrue, updateIfFalse, options)

要有选择地更新部分,您需要执行多个步骤或使用
$set

更新整个文档您需要匹配足够的条件,使用文档中存在的精确值选择特定文档,然后发送创建文档所需的所有数据(如果需要)不存在。此外,如果文档不存在,则需要指定创建该文档的选项

update( {name: "John", surname: "Connor" }, 
        { $set :
             {name: "John", surname: "Connor", age: 32, terminated: false}},
        { upsert: true })
请确保您也了解使用
upsert
的本质。查询需要依赖于一个唯一的字段,否则您可能会得到多个具有匹配数据的文档

警告为避免多次插入同一文档,请仅使用 upsert:如果查询字段具有唯一索引,则为true

MongoDB不支持根据查询结果有条件地只更新文档部分的方法。有而不是允许:

updateIf(query, updateIfTrue, updateIfFalse, options)

要有选择地更新部分,您需要执行多个步骤,或者使用
$set

更新整个文档。我在我的项目中也做了同样的操作,我使用的方法是先检查是否有记录,然后插入,如果有记录,然后更新,因此两个查询都会运行,但只有一个查询会在通过我的检查后运行。我认为DB不应该这样做实现此逻辑。这是程序的唯一逻辑,为什么它应该在数据库中?您应该检查find query是否返回任何内容(在这里,如果需要,您可以使用limit 1检查是否存在)并执行一个或另一个更新查询。这不是DB的逻辑…问题是,当您有1000个工作人员想要升级时,使用升级会使您线程安全。使用两个步骤(查找和更新/插入)可能会产生多个JC,除非您将名称和姓氏设置为唯一索引(但我不知道如何将它们设置为仅作为一对名称和姓氏的唯一性,除非创建一个额外字段来连接它们并使其唯一)不存在,不允许您完全这样做?请注意:稍后检查此问题,并在适当的情况下给出涉及
$setOnInsert
的答案。我在我的项目中也做了同样的操作,我使用的方法是先检查是否没有记录,然后插入,然后更新,因此两个查询都会运行,但只有一个查询会在通过后运行