通过_id的MongoDB Node.js deleteOne不能处理ObjectId

时间:2016-12-19 18:05:44

标签: javascript node.js mongodb jasmine

我试图在mongo数据库包装器上编写测试(规范)并偶然发现这个奇怪的问题。

我的代码构建在mongodb的瘦包装之上,将_id作为字符串暴露给世界,但在与mongo交谈时使用(转换)它们到ObjectId。

我是帮手创建灯具:

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;
    });
};

我使用jasmine进行测试,我在每个beforeEach调用它,以便始终以相同的情况开始每个测试。

然后我有一个测试删除的功能(简单地说):

var dataToDelete = fixtureData[0];
sut.deleteDocument(dataToDelete_.id)
    .then(function(result) {
        expect(....);
    });

在我的deleteDocument中,我没有做任何特别的事情:

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;
    });

这里的theId变量是通过一个非常简单的函数在mongo ObjectId转换为参数传递的参数获得的:

function (id) {
    if (_.isString(id)) {
        return MongoDb.ObjectId(id);
    }
    if (MongoDb.ObjectId.isValid(id) === true) {
        return id;
    }
    throw new Error('Invalid ObjectId');
};

我正在使用mongodb Node.js驱动程序版本2.2.16

这里的问题是,如果我使用deletedCount = 0作为ObjectId,我总是会收到_id,但如果我将其转换为字符串,则可以使用并删除该函数。

这完全困扰我,因为我发现的每个文档和每个示例总是说_idObjectId

有人能解释一下发生了什么吗?

编辑:(答案让我朝着正确的方向前进,但如果你最终遇到这种情况,这就是你正在寻找的真正的答案)如果你在这种情况下结束了你在_id传递字符串创建文档时的字段。如果不是这样的话,请找出你为什么这样做并且你要解决它

1 个答案:

答案 0 :(得分:1)

你确定你的灯具在不同的测试之间没有受损吗?

顺便说一句不应该

return MongoDb.ObjectId(id);

return new MongoDb.ObjectId(id);