Kaedah ini adalah satu-satunya kaedah yang saya rasa lebih boleh dilaksanakan dan konsisten dengan ciri-ciri redis selepas mengamalkannya dan menggabungkannya dengan pendapat yang diberikan oleh pendahulu saya dalam artikel sebelum ini. Namun, pada akhirnya, ia masih tidak secekap ingatan.
Untuk idea pelaksanaan terperinci, sila lihat blog pengarang Redis (Rujukan 1 Contoh di sini masih berdasarkan Nama Pengguna, dalam bahasa Inggeris, dan hanya melakukan segmentasi perkataan dengan panjang 3 untuk frasa diri sendiri untuk senario lain.
Mula-mula berdasarkan carian surat AutoComplete, maka kita perlu melakukan segmentasi perkataan untuk semua Nama, iaitu:
abc => (a, ab, abc)
Apabila kita masukkan a, kita akan terus dapat isi set a bila kita masukkan ab, kita akan dapat terus isi set ab. Kemudian kita mulakan penukaran. Mula-mula kita perlu membahagikan nama jadual Pengguna:
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 != '' 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()); }); }
Langkah 1: Gunakan SQL untuk mengisih dan menapis 20 keping data pertama untuk setiap segmen Sintaks OrmLite digunakan di sini.
Bahagian 2: Simpan ke RedisSet Ambil perhatian bahawa ini hanyalah indeks dan tidak menyimpan kandungan Pengguna tertentu
Apabila mencari, kami boleh melaksanakan perkara berikut:
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()); } }
Selepas ujian sebenar, kaedah penulisan ini sememangnya jauh lebih baik daripada Kekunci sebelumnya, tetapi prestasinya masih tidak memuaskan.
Kaedah ini ditemui selepas saya menyemak dokumentasi Redis, tetapi walaupun ia diuji, dianggarkan ia tidak boleh digunakan untuk pertanyaan berskala besar dalam persekitaran pengeluaran .
Mengikut struktur data yang berbeza, Imbasan dibahagikan kepada SCAN, HSCAN, SSCAN dan ZSCAN. Lihat dokumentasi untuk butiran lanjut. Kami menggunakan ZSCAN di sini:
Kursor kekunci ZSCAN [Corak PERLAWANAN] [COUNT count]
Di sini kursor ialah kursor untuk lelaran carian saya masih belum mengetahuinya kiraan peraturan yang sepadan. Ia ialah bilangan rekod
Memandangkan saya menggunakan StackExchange.Redis, kaedah zscan yang disediakannya ialah:
IEnumerable SortedSetScan(RedisKey key, RedisValue pattern = null, int pageSize = 10, kursor panjang = 0, int pageOffset = 0, bendera CommandFlags = CommandFlags.Tiada);
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); }
Kemudian carian adalah seperti berikut:
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; }
Atas ialah kandungan terperinci Cara menggunakan kaedah indeks segmentasi perkataan Redis. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!