This seems to be a "buggy" response from mongojs which likely results from it's implementation of returning the "inserted" object as a response. The "core" driver does not do this but would either return a "ok" response or an error:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost/test', function(err,db) {
var collection = db.collection('users');
collection.insert({ "username": 2 },function(err,res) {
if (err) throw err;
console.log( res );
});
});
So it seems that mongojs
"mucks this up" while attempting this change in the API behaviour. Consequently, the errors from Bulk operations are also not properly reported. But at least you can get a response that tells you for sure that nothing is actually inserted:
var mongojs = require('mongojs'),
db = mongojs('test');
var collection = db.collection('users')
var bulk = collection.initializeOrderedBulkOp();
bulk.insert({ "username": 2 });
bulk.execute(function(err,res) {
if (err) throw err;
console.log( res );
});
If the username exists then the response would be:
{ writeErrors: [],
writeConcernErrors: [],
nInserted: 0,
nUpserted: 0,
nMatched: 0,
nModified: 0,
nRemoved: 0,
upserted: [],
ok: 1 }
If it's a new "unique" value then the response would be:
{ writeErrors: [],
writeConcernErrors: [],
nInserted: 1,
nUpserted: 0,
nMatched: 0,
nModified: 0,
nRemoved: 0,
upserted: [],
ok: 1 }
If you wanted the _id
of a new document at least, I would have said to use "upserts" with Bulk operations, but the implementation there is broken as well. In fact the "wrapping" methods still done by monjojs
do not include any option to use "upserts" at all.
So the final thing you can do is use the .runCommand()
method from the db
object and process the "upsert" that way:
var mongojs = require('mongojs'),
db = mongojs('test');
db.runCommand(
{
"update": "users",
"updates": [
{
"q": { "username": 4 },
"u": { "$setOnInsert": { "username": 4 } },
"upsert": true
}
],
"ordered": true
},
function(err,res) {
if (err) throw err;
console.log( res );
}
);
It still does not report the error for the duplicate key ( upserts won't do that ) but the response at least tells you the relevant information. On "upsert" it will report this:
{ ok: 1,
nModified: 0,
n: 1,
upserted: [ { index: 0, _id: 5580da465e2076d9ea0c5885 } ] }
And where the value is found and the data is therefore not modified due to $setOnInsert
then the response would be:
{ ok: 1, nModified: 0, n: 1 }
So if you are going to still work with mongojs
then you need to accept the limitations and work around them as demonstrated.