mongodb - 解释为什么在 upsert 上重复输入
问题描述
假设我有这个集合:
db.item.find().pretty()
{
"_id" : ObjectId("5c5635194b6929067972b85c"),
"name" : "car",
"attributes" : [
{
"color" : "blue",
"qty" : 10
}
]
}
如果它不存在,我想在嵌入的“属性”文档中添加一个新条目,否则只进行更新。我根据 MongoDb 文档构建了以下查询来执行此操作:
db.item.update({"name":"car"}, {"$push" : {"attributes" : {"color": "red", "qty": 20}}}, upsert=true)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
这有效,我得到了这个:
db.item.find({"name":"car"}).pretty()
{
"_id" : ObjectId("5c5635194b6929067972b85c"),
"name" : "car",
"attributes" : [
{
"color" : "blue",
"qty" : 10
},
{
"color" : "red",
"qty" : 20
}
]
}
但是,如果我再次运行查询,我会添加一个重复的条目:
db.item.update({"name":"car"}, {"$push" : {"attributes" : {"color": "red", "qty": 20}}}, upsert=true)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.item.find({"name":"car"}).pretty()
{
"_id" : ObjectId("5c5635194b6929067972b85c"),
"name" : "car",
"attributes" : [
{
"color" : "blue",
"qty" : 10
},
{
"color" : "red",
"qty" : 20
},
{
"color" : "red",
"qty" : 20
}
]
}
为什么会这样?upsert 应该防止这种情况,还是我误解了 upsert 的功能?
解决方案
upsert 是更新或插入,如果匹配的文档存在,则更新将完成,否则插入。
在您的情况下,您已经有一个匹配的文档,因此将完成更新。$push
不检查重复项,您需要使用$addToSet
如果要避免重复,则需要使用$addToSet
db.item.update(
{"name":"car"},
{"$addToSet" : {"attributes" : {"color": "red", "qty": 20}}},
{upsert:true}
)
第二次更新结果
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
推荐阅读
- python - 从 TensorFlow 数据集中分离多个输入
- jquery - iOS 14 wkwebview 中触摸事件的 cpu 使用率高
- ruby-on-rails - Rails 批量更新所有 NOT IN 条件
- javascript - React 组件工作正常,但尝试使用 useMemo() 会导致错误
- java - 使用 jar 文件在临时文件夹中创建 excel 文件时,Excel 文件已损坏
- python - python看门狗跟踪来自另一个进程的单个文件更改在检测到更改时失败
- ruby-on-rails - 未定义的局部变量或方法 `permitted_task_attributes' for #
我有一个遵循 Spree/Solidus 范式的解决方案,它封装了允许的参数。我没有能力改变它,而是效仿。但是,我遇到了一个问题,我无法重现 #Api::V1::TasksController:0x0000000000b7c0 的未定义局部变量或方法“permitted_task_attributes”。
- python - 如何在 for 循环中附加熊猫数据框,同时在第一列上进行累积和?
- javascript - 使用 regex machers 加速和简化多个 if/else
- javascript - 基于年月组合的对象组数组