web-dev-qa-db-ja.com

NODEでのRedisSCANの使用

いくつかの形式のキーがたくさんあるRedisがあり、いくつかのパターンに一致するキーを取得して、それらに対していくつかの操作を実行したいと考えています。 KEYSメソッドは本番環境では推奨されないため、使用しません。 SCANを使用して、コードでそれを書くための最良の方法は何であるか疑問に思います。 whileループのようなことをしなければなりませんが、promiseを使用すると、現在のソリューションは次のようになります(コードは少し簡略化されています)。

'use strict'
const Promise = require('bluebird');
const config = require('./config');
const client = require('./clinet');

let iterator = 0;
Promise.coroutine(function* () {
  do {
    iterator = yield clinet.scanAsync(iterator, 'myQuery', 'COUNT', config.scanChunkSize)
      .then(data => {
        let nextIterator = data[0];
        let values = data[1];
        //do some magic with values
        return nextIterator;
      })
  } while (iterator !== '0');
})();

私が行方不明になっていることを行うためのより良い方法はありますか?

7
Madbrush

再帰を使用して、完了するまでスキャンを呼び出し続けることができます。

function scanAsync(cursor, pattern, returnSet){

    return redisClient.scanAsync(cursor, "MATCH", pattern, "COUNT", "100").then(
        function (reply) {

            cursor = reply[0];
            var keys = reply[1];
            keys.forEach(function(key,i){
                returnSet.add(key);
            });

            if( cursor === '0' ){
                return Array.from(returnSet);
            }else{
                return scanAsync(cursor, pattern, returnSet)
            }

    });
}

Set()を渡して、キーが重複していないことを確認します

myResults = new Set();

scanAsync('0', "NOC-*[^listen]*", myResults).map( 
    function( myResults ){ console.log( myResults); }
);
18
Kai

このスニペットを試して、反復ごとにscan(1000)キーを実行し、「削除」することができます。

var cursor = '0';
function scan(pattern,callback){

  redisClient.scan(cursor, 'MATCH',pattern,'COUNT', '1000', function(err, reply){
    if(err){
        throw err;
    }
    cursor = reply[0];
    if(cursor === '0'){
        return callback();
    }else{

        var keys = reply[1];
        keys.forEach(function(key,i){                   
            redisClient.del(key, function(deleteErr, deleteSuccess){
                console.log(key);
            });
        });


        return scan(pattern,callback);
    }
  });
}

scan(strkey,function(){
    console.log('Scan Complete');
});
9
Aniket J kamble

これは本当に古い質問だと思いますが、他のすべての回答は非常に満足のいくものではありませんでした。これは、async awaitを使用して比較的クリーンな方法でスキャンするさらに別の試みです(さらに別の外部依存関係を使用せずに)。これを簡単に変更して、見つかったキーの各セットを継続的に削除できます(LOTSがある場合は、このようなバッチでそれらに取り組む必要があります)。それらを配列にプッシュすることは、この段階でそれらを使用して実行できる非常に基本的なことの1つを示しています。

const redis = require('redis');
const { promisify } = require('util');

const client = redis.createClient({...opts});
const scan = promisify(client.scan).bind(client);

const scanAll = async (pattern) => {
  const found = [];
  let cursor = '0';

  do {
    const reply = await scan(cursor, 'MATCH', pattern);

    cursor = reply[0];
    found.Push(...reply[1]);
  } while (cursor !== '0');

  return found;
}
5
J.Wolfe

これを通過してください、それは役立つかもしれません。

https://github.com/fritzy/node-redisscan

ライブラリをそのまま使用しないでください。 https://github.com/fritzy/node-redisscan/blob/master/index.js で入手できるコードを確認してください。

0
Nishant

Redisのノードバインディングは、ここで呼び出し元に過度の責任を負わせていると思います。そこで、ノードでジェネレーターを使用して、スキャン用の独自のライブラリーも作成しました。

const redis = require('redis')
const client = redis.createClient(…)
const generators = require('redis-async-gen')
const { keysMatching } = generators.using(client)

…

for await (const key of keysMatching('test*')) {
  console.info(key)
}

それは明らかにあなたが気にかけるべきことである最後のビットです。自分でイテレータを注意深く制御する代わりに、理解のためにを使用するだけです。

私はそれについてもっと書いた ここ

0