在NodeJS中使用Mongoose+Mockgoose更新时忽略了唯一索引

Unique index ignored when updating with Mongoose + Mockgoose in NodeJS

本文关键字:唯一 索引 更新 NodeJS Mongoose+Mockgoose      更新时间:2023-09-26

我目前在NodeJS应用程序中使用Mongoose ODM管理与MongoDB的数据库连接,并在Mocha测试中使用Mockgoose拦截连接。我遇到了一个问题,在对文档执行更新时,我的唯一索引被忽略了。我只是用另一个名为Mongoose bird的包来包装Mongoose,它只允许使用promise。

一个特别的模式如下:

// Gallery.js
'use strict';
var mongoose = require('mongoose-bird')(require("mongoose"));
var Schema = mongoose.Schema;
var ObjectId = Schema.Types.ObjectId;
var deepPopulate = require('mongoose-deep-populate')(mongoose);
var GallerySchema = new Schema({
    _id: ObjectId,
    type: String,
    title: String,
    slug: String,
    _albums: [{
        type: ObjectId,
        ref: 'Albums'
    }]
});
GallerySchema.index({ slug: 1 }, { unique: true });
GallerySchema.plugin(deepPopulate, {});
mongoose.model('Galleries', GallerySchema);

当在测试中从我的控制器调用Gallery.update(conditions, data, opts)时,故意将slug设置为另一个的副本,它会更新文档,然后我得到两个具有相同slug路径的文档。

仅供参考,我已经找到了一种方法,使用save()函数来代替它,它似乎毫无疑问地遵循了唯一索引。

然而,由于我更喜欢使用update()而不是save()(即每次更新部分文档而不是整个文档),我很想知道是否有其他人也遇到过同样的问题,以及您是如何克服的?

该应用程序遵循基于MEAN.js的标准MVC模式,因此它不仅仅是一个模型,但如果我遗漏了任何可能有用的内容,请告诉我。

更新
在查看了Mockgoose NPM模块的源代码后,我可以确认在运行update()时从未执行过针对模式的验证。此处记录了一个问题:http://www.github.com/mccormicka/Mockgoose/issues/58

可能您正在测试挂钩中使用mockgoose.reset(例如afterEach)。它会删除数据库,并且在执行过程中不会再次创建索引。

解决方案是单独删除模型。

添加到Diego的帖子中。在测试挂钩中调用mockgoose.helper.reset()以可能清除临时存储中的集合也会删除索引。您应该在使用下面的代码段调用reset之后重置索引。

await mockgoose.helper.reset()
const db = mongoose.connection
db.modelNames().map(async (model) => {
  await db.models[model].createIndexes()
})

这为我解决了问题。希望这能有所帮助。

来自猫鼬文档

当你的应用程序启动时,Mongoose会自动调用模式中每个定义索引的ensureIndex。Mongoose会呼叫依次为每个索引设置ensureIndex,并在上发出"index"事件所有ensureIndex调用成功时的模型,或者错误。

虽然对开发来说很好,但建议使用这种行为在生产中被禁用,因为创建索引可能会导致性能影响。通过设置autoIndex禁用行为将您的模式选项设置为false,或通过将选项config.autoIndex设置为false。

由于mongoose在启动时设置了索引,您需要调试特定的错误,为什么mongoDb不允许使用以下代码进行索引

//keeping autoIndex to true to ensure mongoose creates indexes on app start
GallerySchema.set('autoIndex', true);
//enable index debugging
GallerySchema.set('emitIndexErrors', false);
GallerySchema.on('error', function(error) {
  // gets an error whenever index build fails
});
GallerySchema.index({ slug: 1 }, { unique: true });

此外,请确保autoIndex没有像mongoose文档中提到的那样设置为false,或者最好像上面所做的那样显式设置为true。

此外,

mongoose.set('debug', true);

调试日志将显示它为您创建索引而进行的ensureIndex调用。