问题
I'm trying to write test (spec) on a mongo DB wrapper and stumbled on this weird issue.
My code, build on top of a thin wrapper of mongodb, expose _id
as string to the world but use (convert) them to ObjectId when talking to mongo.
I've an helper creating fixtures:
var _ = require('lodash'),
Promise = require('bluebird'),
MongoDb = require('mongodb');
var fixtureData = [
{
'uuid': '1',
'owner': 'A',
'data': 'someData1'
},
{
'uuid': '2',
'owner': 'A',
'data': 'someData2'
},
{
'uuid': '3',
'owner': 'B',
'data': 'someData3'
},
{
'uuid': '4',
'owner': 'A',
'data': 'someData4'
},
{
'uuid': '5',
'owner': 'A',
'data': 'someData5'
},
{
'uuid': '6',
'owner': 'B',
'data': 'someData6'
}
]
module.exports.loadFixtures = function (url, collectionName) {
var MongoClient = MongoDb.MongoClient;
return MongoClient.connect(url, {
promiseLibrary: Promise
}).then(function (db) {
return db.dropCollection(collectionName)
.catch(function (err) {
if (err.message === 'ns not found') {
return 'does not exist';
}
throw err;
})
.then(function () {
return db.collection(collectionName).insertMany(fixtureData);
}).then(function (result) {
_.forEach(result.insertedIds, function (value, idx) {
fixtureData[idx]._id = value;
});
return db;
});
}).then(function (db) {
db.close();
return fixtureData;
});
};
I use jasmine to test and I call this at every beforeEach to always start each test with the same exact situation.
I then have a function to test the delete (simplyfing):
var dataToDelete = fixtureData[0];
sut.deleteDocument(dataToDelete_.id)
.then(function(result) {
expect(....);
});
Inside my deleteDocument I do nothing special:
db.collection('myCollection').deleteOne({ _id: theId })
then(function(result)) {
if (result.deletedCount === 0) {
throw new Error('No document to delete with ID: ' + _id);
}
return null;
});
The theId
variable here is obtained converting in a mongo ObjectId
the id passed as parameter with a very simple function:
function (id) {
if (_.isString(id)) {
return MongoDb.ObjectId(id);
}
if (MongoDb.ObjectId.isValid(id) === true) {
return id;
}
throw new Error('Invalid ObjectId');
};
I'm using mongodb Node.js driver version 2.2.16
.
The problem here is that I ALWAYS receive a deletedCount = 0
if I use an ObjectId
as _id
but if I covert it to String it works and delete the function.
This completely puzzle me because every documentation I've found and every example always say _id
is a ObjectId
.
Can someone explain what's going on?
EDIT: (the answer got me in the right direction but this is the actual anwer you are looking for if you end up in this situation) if you end up in this situation you are passing strings in the _id
field when creating the document. Find out why you do that if it is not intended and you'll fix it
回答1:
Are you sure your fixtures aren't mangled between different tests?
And by the way shouldn't
return MongoDb.ObjectId(id);
be
return new MongoDb.ObjectId(id);
?
来源:https://stackoverflow.com/questions/41228499/mongodb-node-js-deleteone-via-id-doesnt-work-on-objectid