ホームページ  >  記事  >  データベース  >  Redis の単語分割インデックス方式の使用方法

Redis の単語分割インデックス方式の使用方法

王林
王林転載
2023-05-26 17:28:52981ブラウズ

Word Segmentation Index Method

実践後、前回の記事で先人たちの意見を踏まえ、より実現可能でredisの特性に合致していると思うのはこの方法だけですが、 、結局のところ、メモリほど効率的ではありません。

詳細な実装アイデアについては、Redis 作者のブログ (参考 1) を参照してください。ここでの例は、依然として英語の UserName に基づいており、フレーズの長さ 3 の単語の分割のみを行っています。他のシナリオでは自分自身を使用してください。

最初にオートコンプリートの文字検索に基づいて、次にすべての名前に対して単語の分割を行う必要があります:

abc => (a, ab, abc)

When a を入力するとセット a の内容が直接取得され、ab と入力するとセット ab の内容が直接取得されます。次に、変換を開始します。まず、User テーブルの名前をセグメント化する必要があります:

var redis = ConnectionMultiplexer.Connect("localhost");var db = redis.GetDatabase();for (var i = 1; i < 4; i++)
{    var data = dbCon.Lookup<string, int>(string.Format(@"select words, id from (
                                    select Row_number() over (partition by words order by name) as rn,id,words from (
                                        select  id, SUBSTRING(name, 1, {0}) as words, name from User 
                                    ) as t
                                    ) t2 where rn <= {1} and words != &#39;&#39; and words is not null", i, 20));

    data.ForEach((key, item) =>  {
         db.SetAdd("capqueen:Cache:user:" + key.ToLower(), item.Select<int, RedisValue>(j => j).ToArray());
      });
}

ステップ 1: SQL を使用して、各セグメントの最初の 20 個のデータを並べ替え、フィルターで除外します。OrmLite の構文は次のとおりです。こちらで使用しております。

パート 2: RedisSet に保存します。これは単なるインデックスであり、特定のユーザー コンテンツを保存するわけではないことに注意してください。

検索する場合、次を実装できます:

public List<User> SearchWords(string keywords)
{            var redis = ConnectionMultiplexer.Connect("localhost");            var db = redis.GetDatabase();            var result = db.SetMembers("capqueen:Cache:user:" + keywords.ToLower());            var users = new List<User>();            if (result.Any())
            {                //转换成ids                var ids = result.ToList().Select<RedisValue, RedisKey>(i => i.ToString());                //按照keys获取value ,事先已经存好了Usersvar values = db.StringGet(ids.ToArray());                //构造List Json以加速解析var portsJson = new StringBuilder("[");

                values.ToList().ForEach(item =>{                    if (!string.IsNullOrWhiteSpace(item))
                    {
                        portsJson.Append(item).Append(",");
                    }
                });

                portsJson.Append("]");

                users = JsonConvert.DeserializeObject<List<User>>(portsJson.ToString());
            }
}

実際にテストした結果、この書き込み方法は確かに以前のキーよりもはるかに優れていますが、パフォーマンスはまだ満足のいくものではありません。

スキャン検索メソッド

このメソッドは Redis のドキュメントを参照して私が発見しましたが、テストとはいえ、大規模なクエリには使用できないと推測されます。本番環境。

さまざまなデータ構造に応じて、スキャンは SCAN、HSCAN、SSCAN、ZSCAN に分類されます。詳細については、ドキュメントを参照してください。ここでは ZSCAN を使用します:

ZSCAN キー カーソル [MATCH パターン] [COUNT カウント]

ここでのカーソルは検索反復用のカーソルです。まだ理解していません。パターンは一致するルールの数です。レコードの数です

StackExchange.Redis を使用しているため、提供される zscan メソッドは次のとおりです:

IEnumerable SortedSetScan(RedisKey key, RedisValue pattern = null, int pageSize) = 10、ロング カーソル = 0、int pageOffset = 0、CommandFlags flags = CommandFlags.None);

public void CreateTerminalCache(List<User> users)
{            if (users == null) return;            var db = ConnectionMultiplexer.GetDatabase();            var sourceData = new List<KeyValuePair<RedisKey, RedisValue>>();            //构造集合数据var list = users.Select(item =>{                var value = JsonConvert.SerializeObject(item);                //构造原始数据sourceData.Add(new KeyValuePair<RedisKey, RedisValue>("capqueen:users:" + item.Id, value));                //构造数据    return new SortedSetEntry(item.Name, item.Id);
            });            //添加进有序集合,采用name - id db.SortedSetAdd("capqueen:users:index", list.ToArray());            //添加港口数据key-value            db.StringSet(sourceData.ToArray(), When.Always, CommandFlags.None);
}

その後、検索は次のようになります:

public List<User> GetUserByWord(string words)
{            var db = ConnectionMultiplexer.GetDatabase();            //搜索var result = db.SortedSetScan("capqueen:users:index", words + "*", 10, 1, 30, CommandFlags.None).Take(30).ToList();           var users = new List<User>();            if (result.Any())
            {                //转换成ids                var ids = result.ToList().Select<SortedSetEntry, RedisKey>(i => i.ToString());                //按照keys获取valuevar values = db.StringGet(ids.ToArray());                //构造List Json以加速解析var portsJson = new StringBuilder("[");

                values.ToList().ForEach(item =>{                    if (!string.IsNullOrWhiteSpace(item))
                    {
                        portsJson.Append(item).Append(",");
                    }
                });

                portsJson.Append("]");

                users = JsonConvert.DeserializeObject<List<User>>(portsJson.ToString());
            }            return users;
}

以上がRedis の単語分割インデックス方式の使用方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。