21

我需要为 MongoDB 数据库创建几个部署脚本,例如数据迁移和固定装置,但我找不到有关如何使用 Mongoose API 删除索引的足够信息。这在使用官方 MongoDB API 时非常简单:

删除指定集合上的所有索引:

db.collection.dropIndexes();

但是,我想为此使用 Mongoose,并尝试使用executeDbCommand改编自这篇文章,但没有成功:

mongoose.connection.db.executeDbCommand({ dropIndexes: collectionName, index: '*' },
  function(err, result) { /* ... */ });

我应该使用 Node.js 的官方 MongoDB API 还是我在这种方法中遗漏了一些东西?

4

5 回答 5

37

要通过集合的 Mongoose 模型执行此操作,您可以调用dropAllIndexes本机集合:

MyModel.collection.dropAllIndexes(function (err, results) {
    // Handle errors
});

更新

dropAllIndexes在本机驱动程序的 2.x 版本中已弃用,因此dropIndexes应改为使用:

MyModel.collection.dropIndexes(function (err, results) {
    // Handle errors
});
于 2012-10-22T16:41:20.590 回答
9

如果您想使用 mongoose 维护架构定义中的索引(如果您使用的是 mongoose,您可能会这样做),您可以轻松删除不再使用的索引并创建尚不存在的索引。await YourModel.syncIndexes()您可以在需要同步的任何模型上运行一次。它将在后台创建.ensureIndexes并删除架构定义中不再存在的任何内容。您可以在此处查看完整文档: https ://mongoosejs.com/docs/api.html#model_Model.syncIndexes

于 2019-09-28T01:57:59.210 回答
1

看起来您正试图删除给定集合上的所有索引。

根据 MongoDB Docs,这是正确的命令

...我尝试使用改编自这篇文章的 executeDbCommand,但没有成功:

为了在这里真正提供帮助,我们需要更多详细信息:

  • 什么失败了?你如何衡量“没有成功”?
  • 你能 100% 确认命令运行了吗?您是否在回调中输出到日志?你检查err变量了吗?
  • 你在哪里创建索引?你能确认你没有在掉落后重新创建它们吗?
  • 您是否在列出特定索引名称时尝试过该命令?老实说,您不应该使用"*". 您应该删除并创建非常具体的索引。
于 2012-10-22T16:38:25.460 回答
0

这可能不是发布此内容的最佳位置,但我认为无论如何都值得发布。

每次针对 db 连接定义/创建模型时,我都会调用model.syncIndexes(),这可以确保索引是最新的并且与模式保持同步,但是由于它已在线突出显示(示例),这可能会在分布式架构中产生问题,多个服务器同时尝试相同的操作。如果使用类似库之类的东西在同一台机器上的多个内核上生成主/从实例,这一点尤其重要cluster,因为当整个服务器启动时,它们通常会在彼此靠近的地方启动。

参考上面的“codebarbarian”文章,当他们说:

Mongoose 不会为您调用 syncIndexes(),您需要自己负责调用 syncIndexes()。这有几个原因,最值得注意的是 syncIndexes() 不执行任何类型的分布式锁定。如果您有多个在启动时调用 syncIndexes() 的服务器,您可能会因为尝试删除不再存在的索引而出错。

所以我要做的是创建一个函数,它使用 redis 和 redis redlock 来获得一段名义时间的租约,以防止多个工作人员(实际上是多个服务器中的多个工作人员)同时尝试相同的同步操作。

它也绕过了整个事情,除非它是试图执行操作的“主人”,我认为将这项工作委托给任何工人都没有任何实际意义。

const cluster               = require('cluster');
const {logger}              = require("$/src/logger");
const { 
    redlock, 
    LockError
}                           = require("$/src/services/redis");
const mongoose              = require('mongoose');

// Check is mongoose model, 
// ref: https://stackoverflow.com/a/56815793/1834057
const isMongoModel = (obj) => {
    return obj.hasOwnProperty('schema') && obj.schema instanceof mongoose.Schema;
}

const syncIndexesWithRedlock = (model,duration=60000) => new Promise(resolve => {

    // Ensure the cluster is master
    if(!cluster.isMaster) 
        return resolve(false)

    // Now attempt to gain redlock and sync indexes
    try {

        // Typecheck
        if(!model || !isMongoModel(model))
            throw new Error('model argument is required and must be a mongoose model');

        if(isNaN(duration) || duration <= 0)
            throw new Error('duration argument is required, and must be positive numeric')

        // Extract name
        let name        = model.collection.collectionName;

        // Define the redlock resource
        let resource    = `syncIndexes/${name}`;

        // Coerce Duration to Integer
        // Not sure if this is strictly required, but wtf. 
        // Will ensure the duration is at least 1ms, given that duration <= 0 throws error above
        let redlockLeaseDuration = Math.ceil(duration);

        // Attempt to gain lock and sync indexes
        redlock.lock(resource,redlockLeaseDuration)
            .then(() => {
                // Sync Indexes
                model.syncIndexes();

                // Success
                resolve(true);
            })
            .catch(err => {
                
                // Report Lock Error
                if(err instanceof LockError){
                    logger.error(`Redlock LockError -- ${err.message}`);

                // Report Other Errors
                }else{
                    logger.error(err.message);
                }

                // Fail, Either LockError error or some other error
                return resolve(false);
            })

    // General Fail for whatever reason
    }catch(err){
        logger.error(err.message);
        return resolve(false);
    }
});

我不会设置 Redis 连接,这是其他线程的主题,但上面这段代码的重点是展示如何syncIndexes()可靠地使用并防止一个线程删除索引而另一个线程尝试删除相同索引的问题,或尝试同时修改索引的其他分布式问题。

于 2021-11-27T02:56:32.067 回答
-2

删除您可以使用的特定索引

db.users.dropIndex("your_index_name_here")
于 2020-01-18T09:33:33.970 回答