使用mongodb-native-driver保存文档更新时,我收到了重复的文档。我第一次调用save()
正确创建了文档,并添加了一个带有ObjectID值的_id。第二次调用使用原始ObjectID的文本_id创建一个新文档。例如,我最终得到:
> db.people.find()
{ "firstname" : "Fred", "lastname" : "Flintstone", "_id" : ObjectId("52e55737ae49620000fd894e") }
{ "firstname" : "Fred", "lastname" : "Flintstone with a change", "_id" : "52e55737ae49620000fd894e" }
我的第一次电话正确创建了Fred Flinstone。第二次调用将“带有更改”添加到姓氏,创建了第二个文档。
我正在使用MongoDB 2.4.8和mongo-native-driver 1.3.23。
这是我的NodeJS / Express端点:
app.post("/contacts", function (req, res) {
console.log("POST /contacts, req.body: " + JSON.stringify(req.body));
db.collection("people").save(req.body, function (err, inserted) {
if (err) {
throw err;
} else {
console.dir("Successfully inserted/updated: " + JSON.stringify(inserted));
res.send(inserted);
}
});
});
以下是运行时日志消息:
POST /contacts, req.body: {"firstname":"Fred","lastname":"Flintstone"}
'Successfully inserted/updated: {"firstname":"Fred","lastname":"Flintstone","_id":"52e55737ae49620000fd894e"}'
POST /contacts, req.body: {"firstname":"Fred","lastname":"Flintstone with a change","_id":"52e55737ae49620000fd894e"}
'Successfully inserted/updated: 1'
为什么我的第二次更新现有记录?驱动程序是否未将_id值转换为ObjectID?
答案 0 :(得分:3)
第二次发布的内容包含一个名为“_id”的字段,它是一个字符串。这就是问题所在。
查看文档,save method所做的是“简单的完整文档替换功能”。我不经常使用这个功能退出,所以这就是我猜的。该函数使用_id字段查找文档,然后将完整文档替换为您提供的文档。但是,您提供的是字符串_id。显然它不等于ObjectId。我认为你应该在传递给函数之前将它包装到ObjectId。
此外,根据文档不建议使用save方法。您应该使用update(可能带有upsert选项)而不是
答案 1 :(得分:1)
我不知道为什么会创建第二个文档,但为什么不使用更新功能(可能使用 upsert 运算符)?
更新操作的示例:
var query = { '_id': '52e55737ae49620000fd894e' };
db.collection('people').findOne(query, function (err, doc) {
if (err) throw err;
if (!doc) {
return db.close();
}
doc['lastname'] = 'Flintstone with a change';
db.collection('people').update(query, doc, function (err, updated) {
if (err) throw err;
console.dir('Successfully updated ' + updated + ' document!');
return db.close();
});
});
现在使用upsert运算符:
var query = { '_id': '52e55737ae49620000fd894e' };
var operator = { '$set': { 'lastname': 'Flintstone with a change' } };
var options = { 'upsert': true };
db.collection('people').update(query, operator, options, function (err, upserted) {
if (err) throw err;
console.dir('Successfully upserted ' + upserted + ' document!');
return db.close();
});
不同之处在于upsert运算符将更新文档(如果存在),否则将创建一个新文档。使用upsert运算符时,应记住此操作可能未指定。这意味着如果您的查询中没有足够的信息来标识单个文档,则会插入一个新文档。