MongoDB节点本地驱动程序创build重复的文件

使用mongodb-native-driver将更新保存到文档时,出现重复的文档。 我第一次调用save()正确地创build文档并添加一个带有ObjectID值的_id。 第二个调用创build一个带有原始ObjectID文本_id的新文档。 例如,我结束了:

 > db.people.find() { "firstname" : "Fred", "lastname" : "Flintstone", "_id" : ObjectId("52e55737ae49620000fd894e") } { "firstname" : "Fred", "lastname" : "Flintstone with a change", "_id" : "52e55737ae49620000fd894e" } 

我的第一个电话正确地创build了弗雷德弗林斯通 第二个叫“添加”到姓氏的调用创build了第二个文档。

我使用的是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' 

为什么我的第二个更新现有的logging? 驱动程序是否不将_id值强制转换为ObjectID?

第二次发布的内容包含一个名为“_id”的字段,它是一个string。 那就是问题所在。

看文档, 保存方法做的是“简单的全文档replacefunction”。 我不经常使用这个函数退出所以这是我的猜测。 该函数使用_id字段查找文档,然后用您提供的内容replace整个文档。 但是,您提供的是string_id。 显然它不等于ObjectId。 我想你应该把它包装到一个ObjectId之前传递给函数。

另外,根据文档不build议保存方法。 你应该使用更新 (也许用upsert选项)

我不完全知道为什么会创build第二个文档,但为什么不使用更新function(可能与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操作符会更新文件,否则会创build一个新文件。 当使用upsert操作符时,应该记住这个操作可以被低估。 这意味着如果您的查询不包含足够的信息来识别单个文档,则会插入一个新文档。