MongoDb: 插入或更新具有唯一索引的多个文档
MongoDb: Insert or update multiple documents with a unique index
我有一个带有唯一索引的 MongoDB 集合。
我正在尝试将一组文档插入或更新到该集合中。
如果集合中没有与文档的唯一索引匹配的现有文档,则应将该新文档插入到集合中。
但是,如果集合中已经存在具有该唯一索引的文档,则应使用新文档的字段对其进行更新。新文档中不存在的任何字段都应保持不变。
这是我目前拥有的用于插入(但不用于更新)的内容。
const mongojs = require('mongojs');
const db = mongojs('mongodb://username:password@address.mlab.com:37230/database');
// items is an array of documents
db.items.insert(items, (err, task) => {
if (err) {
console.log(err);
}
})
我知道这是错误的,目前它给出了这个错误:
E11000 duplicate key error index: database.items.$upc_1 dup key:
对此的正确查询是什么?
您要查找的是更新插入,而不是插入。可以通过以下代码完成:
db.collection.update(
<query>,
<updates>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>,
collation: <document>
}
)
查询将使用查询的参数搜索文档,如果找到,它将更新中提到的字段。如果没有找到,它将插入一个新文档,其中包含 的字段和值。
最后一个对象(具有多个字段)包含一个字段,用于说明是否需要更新插入,还有一个名为 "multi" 的字段用于说明是否需要对多个文档进行更新。
例如:
db.items.update({name:"item1"},{$set:{price:20}},{upsert:true})
这将搜索名称为 "item1" 的文档并将其价格设置为 20。如果找不到,它将创建一个价格为 20 的新文档。
不过要注意的一件事是:
如果您不在字段上使用标记 $set,它将替换整个文档。
假设您有这样的文档:
{_id:"1234",name:"item1",price:10}
如果你运行以下两个查询:
db.items.update({name:"item1"},{$set:{price:20}},...)
和
db.items.update({name:"item1"},{price:20},...)
它会产生不同的结果:
第一个:
{_id:"1234",name:"item1",price:20}
第二个:
{_id:"1234",price:20}
如果你不调用$set
,它会改变整个文档。
有关手册的更多信息:
https://docs.mongodb.com/manual/reference/method/db.collection.update/
希望我的回答对您有所帮助
我不相信您可以同时更新整个文档数组。因此,您必须单独更新数组中的每个项目。
items.forEach((item) => {
db.items.update({_id: item._id}, item, {upsert: true}, (err, task) => {
if (err) {
console.log(err);
}
});
}
{upsert: true}
选项将在记录存在时更新,否则插入。
您可以尝试使用 mongodb bulkWrite
api:
var ops = []
items.forEach(item => {
ops.push(
{
updateOne: {
filter: { _id: unique_id },
update: {
$set: { fields_to_set_if_exists },
$setOnInsert: { fileds_to_insert_if_does_not_exist }
},
upsert: true
}
}
)
})
db.collections('collection_name').bulkWrite(ops, { ordered: false });
我有一个带有唯一索引的 MongoDB 集合。 我正在尝试将一组文档插入或更新到该集合中。
如果集合中没有与文档的唯一索引匹配的现有文档,则应将该新文档插入到集合中。
但是,如果集合中已经存在具有该唯一索引的文档,则应使用新文档的字段对其进行更新。新文档中不存在的任何字段都应保持不变。
这是我目前拥有的用于插入(但不用于更新)的内容。
const mongojs = require('mongojs');
const db = mongojs('mongodb://username:password@address.mlab.com:37230/database');
// items is an array of documents
db.items.insert(items, (err, task) => {
if (err) {
console.log(err);
}
})
我知道这是错误的,目前它给出了这个错误:
E11000 duplicate key error index: database.items.$upc_1 dup key:
对此的正确查询是什么?
您要查找的是更新插入,而不是插入。可以通过以下代码完成:
db.collection.update(
<query>,
<updates>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>,
collation: <document>
}
)
查询将使用查询的参数搜索文档,如果找到,它将更新中提到的字段。如果没有找到,它将插入一个新文档,其中包含 的字段和值。
最后一个对象(具有多个字段)包含一个字段,用于说明是否需要更新插入,还有一个名为 "multi" 的字段用于说明是否需要对多个文档进行更新。
例如:
db.items.update({name:"item1"},{$set:{price:20}},{upsert:true})
这将搜索名称为 "item1" 的文档并将其价格设置为 20。如果找不到,它将创建一个价格为 20 的新文档。
不过要注意的一件事是:
如果您不在字段上使用标记 $set,它将替换整个文档。
假设您有这样的文档:
{_id:"1234",name:"item1",price:10}
如果你运行以下两个查询:
db.items.update({name:"item1"},{$set:{price:20}},...)
和
db.items.update({name:"item1"},{price:20},...)
它会产生不同的结果:
第一个:
{_id:"1234",name:"item1",price:20}
第二个:
{_id:"1234",price:20}
如果你不调用$set
,它会改变整个文档。
有关手册的更多信息:
https://docs.mongodb.com/manual/reference/method/db.collection.update/
希望我的回答对您有所帮助
我不相信您可以同时更新整个文档数组。因此,您必须单独更新数组中的每个项目。
items.forEach((item) => {
db.items.update({_id: item._id}, item, {upsert: true}, (err, task) => {
if (err) {
console.log(err);
}
});
}
{upsert: true}
选项将在记录存在时更新,否则插入。
您可以尝试使用 mongodb bulkWrite
api:
var ops = []
items.forEach(item => {
ops.push(
{
updateOne: {
filter: { _id: unique_id },
update: {
$set: { fields_to_set_if_exists },
$setOnInsert: { fileds_to_insert_if_does_not_exist }
},
upsert: true
}
}
)
})
db.collections('collection_name').bulkWrite(ops, { ordered: false });