MongoDB Node.js deleteOne via _id doesn't work on ObjectId

北城以北 提交于 2019-12-25 04:06:50

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!