Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb mongo子文档的pushOrModify-like运算符_Mongodb_Mongodb Query - Fatal编程技术网

Mongodb mongo子文档的pushOrModify-like运算符

Mongodb mongo子文档的pushOrModify-like运算符,mongodb,mongodb-query,Mongodb,Mongodb Query,我想做的是,如果子文档存在,更新它,否则,只通过一种方法推送新的子文档 首先,找到{name:“SweetTown”},然后 如果存在Bob,我想将其声誉更改为30: Town collection { name: "SweetTown", residents: [{ name: "Bob", reputation: 20 }] } 应该是 { name: "SweetTown", residents: [{ name: "Bob", reputation: 30 }] } { name:

我想做的是,如果子文档存在,更新它,否则,只通过一种方法推送新的子文档

首先,找到
{name:“SweetTown”}
,然后

如果存在
Bob
,我想将其声誉更改为
30

Town collection
{ name: "SweetTown", residents: [{ name: "Bob", reputation: 20 }] }
应该是

{ name: "SweetTown", residents: [{ name: "Bob", reputation: 30 }] }
{ name: "SweetTown", residents: [
  { name: "Alice", reputation: 140 },
  { name: "Bob", reputation: 30 }
]}
或否,将
{name:“Bob”,声誉:30}
推送到
居民

Town collection
{ name: "SweetTown", residents: [{ name: "Alice", reputation: 140 }] }
应该是

{ name: "SweetTown", residents: [{ name: "Bob", reputation: 30 }] }
{ name: "SweetTown", residents: [
  { name: "Alice", reputation: 140 },
  { name: "Bob", reputation: 30 }
]}
我对此进行了大量搜索,找到了一些解决方案,如
$addToSet
$push
$ne
upsert
选项

但是,我不能正确地混合这些来解决这个问题。如何使其工作?

这实际上需要“两个”(或“三个”upsert)update语句,这也是“批量”操作存在的一个很好的原因

db.collection.bulkWrite([
//尝试更新匹配的元素
{“updateOne”:{
“筛选器”:{
“姓名”:“甜心镇”,
“居民姓名”:“鲍勃”
},
“更新”:{
“$set”:{“居民.$.声誉”:30}
}
},
//$将元素推到不匹配的位置
{“updateOne”:{
“过滤器”:{
“姓名”:“甜心镇”,
“residents.name”:{“$ne”:“Bob”}
},
“更新”:{
“$push”:{
“居民”:{“姓名”:“鲍勃”,“声誉”:30}
}
} 
}}
])
或者,如果您确实想在
“Sweetton”
的基本文档中包含
“upsert”
,那么您需要将该问题分离到它自己的测试中:

db.collection.bulkWrite([
//尝试更新匹配的元素
{“updateOne”:{
“筛选器”:{
“姓名”:“甜心镇”,
“居民姓名”:“鲍勃”
},
“更新”:{
“$set”:{“居民.$.声誉”:30}
}
},
//$将元素推到不匹配的位置
{“updateOne”:{
“过滤器”:{
“姓名”:“甜心镇”,
“residents.name”:{“$ne”:“Bob”}
},
“更新”:{
“$push”:{
“居民”:{“姓名”:“鲍勃”,“声誉”:30}
}
} 
}},
//仅在实际为upsert时使用$setOnInsert
{“updateOne”:{
“过滤器”:{
“名称”:“糖果城”
},
“更新”:{
“$setOnInsert”:{
“居民”:[{“姓名”:“鲍勃”,“声誉”:30}]
}
},
“向上插入”:正确
}}
])
因此,一般的概念是,只有当
“upsert”
实际发生时,才应用该操作。为了确保这只发生在这种情况下,实际查看数组元素的其他操作没有标记为
“upsert”
选项。该部分是故意的

无论您以何种方式看待它,只有这些操作中的一个才有可能在数据库中实际进行任何修改,因为要么找到了元素,要么没有找到文档,甚至没有创建新的文档

在任何情况下,都不可能在单个update语句中执行此类操作。但是,由于“批量”操作实际上只是一个请求和一个响应,然后就应用程序而言,只需与服务器进行一次对话,服务器就可以尝试这三种方法并返回响应

对于直接批量API的早期使用,备选语法为:

var bulk=db.collection.initializeOrderedBulkOp();
//$set匹配现有的位置
bulk.find({“name”:“SweetTown”,“residents.name”:“Bob”}).updateOne({
“$set”:{“居民.$.声誉”:30}
});
//$push不存在的地方
bulk.find({“name”:“SweetTown”,“residents.name”:{“$ne”:“Bob”}}).updateOne({
“$push”:{“居民”:{“姓名”:“鲍勃”,“声誉”:30}”
});
//仅尝试向上插入
bulk.find({“name”:“SweetTown”}).upsert().updateOne({
“$setOnInsert”:{
“居民”:[{“姓名”:“鲍勃”,“声誉”:30}]
}
})
bulk.execute();

我原以为可以用
findOneAndModify
解决,但这与使用
bulkWrite
操作完全不同。当我遇到这样的问题时,它给了我很多机会。谢谢。