21

MongoDBデータベースのデータ移行やフィクスチャなどのいくつかのデプロイメントスクリプトを作成する必要がありますが、MongooseAPIを使用してインデックスを削除する方法に関する十分な情報を見つけることができませんでした。公式のMongoDBAPIを使用する場合、これは非常に簡単です。

指定されたコレクションのすべてのインデックスを削除するには:

db.collection.dropIndexes();

しかし、私はこれにマングースを使用したいと思い、この投稿executeDbCommandから適応したものを使用しようとしましたが、成功しませんでした:

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

Node.js用の公式MongoDBAPIを使用する必要がありますか、それともこのアプローチで何かを逃しただけですか?

4

5 に答える 5

37

コレクションのマングースモデルを介してこれを行うに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()同期する必要のあるモデルで1回だけ実行できます。.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

これを投稿するのに最適な場所ではないかもしれませんが、とにかく投稿する価値があると思います。

model.syncIndexes()データベース接続に対してモデルが定義/作成されるたびに呼び出します。これにより、インデックスがスキーマで最新かつ最新であることが保証されますが、オンラインで強調表示されているため()、分散アーキテクチャで問題が発生する可能性があります。複数のサーバーが同時に同じ操作を試みている場合。これは、ライブラリのようなものを使用して、同じマシン上の複数のコアでマスター/スレーブインスタンスを生成する場合に特に関係があります。これはcluster、サーバー全体の起動時に、それらが互いに近接して起動することが多いためです。

上記の「codebarbarian」の記事を参照すると、次のように述べられている場合、問題が明確に強調されています。

MongooseはsyncIndexes()を呼び出さないので、syncIndexes()を自分で呼び出す必要があります。これにはいくつかの理由があります。特に、syncIndexes()が分散ロックを実行しないことが理由です。起動時にsyncIndexes()を呼び出すサーバーが複数ある場合は、存在しなくなったインデックスを削除しようとするとエラーが発生する可能性があります。

だから私がやっていることは、複数のワーカー(そして実際には複数のサーバーの複数のワーカー)が同時に同じ同期操作を試みるのを防ぐために、redisとredisredlockを使用してわずかな期間リースを取得する関数を作成することです。

また、操作を実行しようとしているのが「マスター」でない限り、すべてをバイパスします。このジョブをどのワーカーにも委任することに意味はありません。

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 に答える