Redis
 sql >> Teknologi Basis Data >  >> NoSQL >> Redis

Pencarian ulang agregat kembali 5 teratas dari setiap grup

Pertama:

  • Pastikan untuk menonaktifkan fitur yang tidak akan Anda gunakan (NOOFFSETS , NOHL ,NOFREQS , STOPWORDS 0 )
  • Gunakan SORTABLE untuk NUMERIC . Anda score .

Berikut adalah skema yang saya gunakan untuk menguji:

FT.CREATE product_tags NOOFFSETS NOHL NOFREQS STOPWORDS 0
    SCHEMA product_name TEXT tags TAG score NUMERIC SORTABLE

Anda ingin memikirkan FT.AGGREGATE sebagai saluran.

Langkah pertama adalah mengurutkan produk berdasarkan @score, sehingga nanti, di jalur pipa, saat kita REDUCE TOLIST 1 @product_name , daftar keluar diurutkan:

SORTBY 2 @score DESC

Saya pikir Anda sudah melakukan LOAD /APPLY untuk menangani tag, sebagai TAG jika tidak, bidang akan dikelompokkan menurut daftar tag string yang dipisahkan koma, per produk. Lihat Izinkan GROUPBY pada masalah bidang tag. Jadi langkah kita selanjutnya adalah:

LOAD 1 @tags 
APPLY split(@tags) as TAG 

Kami kemudian mengelompokkan berdasarkan @TAG, dan menerapkan dua pengurangan. Daftar produk kami akan diurutkan.

GROUPBY 1 @TAG
    REDUCE SUM 1 @score AS total_score
    REDUCE TOLIST 1 @product_name AS products

Terakhir, kami mengurutkan berdasarkan @total_score :

SORTBY 2 @total_score DESC

Berikut tampilan akhir dari perintah:

FT.AGGREGATE product_tags *
    SORTBY 2 @score DESC 
    LOAD 1 @tags 
    APPLY split(@tags) as TAG
    GROUPBY 1 @TAG
        REDUCE SUM 1 @score AS total_score 
        REDUCE TOLIST 1 @product_name AS products
    SORTBY 2 @total_score DESC

Berikut daftar lengkap perintah untuk mengilustrasikan hasilnya. Saya menggunakan productXX dengan skor XX untuk memverifikasi penyortiran produk secara visual dengan mudah.

> FT.CREATE product_tags NOOFFSETS NOHL NOFREQS STOPWORDS 0 SCHEMA product_name TEXT tags TAG score NUMERIC SORTABLE
OK
> FT.ADD product_tags pt:product10 1 FIELDS product_name product10 tags tag2,tag3,tag4 score 10
OK
> FT.ADD product_tags pt:product1 1 FIELDS product_name product1  tags tag1,tag2,tag3 score 1
OK
> FT.ADD product_tags pt:product100 1 FIELDS product_name product100 tags tag2,tag3 score 100
OK
> FT.ADD product_tags pt:product5 1 FIELDS product_name product5 tags tag1,tag4 score 5
OK
> FT.SEARCH product_tags *
1) (integer) 4
2) "pt:product5"
3) 1) "product_name"
   2) "product5"
   3) "tags"
   4) "tag1,tag4"
   5) "score"
   6) "5"
4) "pt:product100"
5) 1) "product_name"
   2) "product100"
   3) "tags"
   4) "tag2,tag3"
   5) "score"
   6) "100"
6) "pt:product1"
7) 1) "product_name"
   2) "product1"
   3) "tags"
   4) "tag1,tag2,tag3"
   5) "score"
   6) "1"
8) "pt:product10"
9) 1) "product_name"
   2) "product10"
   3) "tags"
   4) "tag2,tag3,tag4"
   5) "score"
   6) "10"
> FT.AGGREGATE product_tags * SORTBY 2 @score DESC LOAD 1 @tags APPLY split(@tags) as TAG GROUPBY 1 @TAG REDUCE SUM 1 @score AS total_score REDUCE TOLIST 1 @product_name AS products SORTBY 2 @total_score DESC
1) (integer) 4
2) 1) "TAG"
   2) "tag2"
   3) "total_score"
   4) "111"
   5) "products"
   6) 1) "product100"
      2) "product10"
      3) "product1"
3) 1) "TAG"
   2) "tag3"
   3) "total_score"
   4) "111"
   5) "products"
   6) 1) "product100"
      2) "product10"
      3) "product1"
4) 1) "TAG"
   2) "tag4"
   3) "total_score"
   4) "15"
   5) "products"
   6) 1) "product10"
      2) "product5"
5) 1) "TAG"
   2) "tag1"
   3) "total_score"
   4) "6"
   5) "products"
   6) 1) "product5"
      2) "product1"

Anda mendapatkan daftar lengkap produk yang diurutkan, bukan hanya 5 teratas. Dari segi kerumitan tidak ada bedanya, kami membayar harganya. Dampaknya ada di buffering, payload jaringan, dan klien Anda.

Anda dapat membatasi hingga 5 teratas menggunakan skrip Lua:

eval "local arr = redis.call('FT.AGGREGATE', KEYS[1], '*', 'SORTBY', '2', '@score', 'DESC', 'LOAD', '1', '@tags', 'APPLY', 'split(@tags)', 'as', 'TAG', 'GROUPBY', '1', '@TAG', 'REDUCE', 'SUM', '1', '@score', 'AS', 'total_score', 'REDUCE', 'TOLIST', '1', '@product_name', 'AS', 'products', 'SORTBY', '2', '@total_score', 'DESC') \n for i=2,(arr[1]+1) do \n arr[i][6] = {unpack(arr[i][6], 1, ARGV[1])} \n end \n return arr" 1 product_tags 5

Berikut tampilan ramah dari skrip Lua di atas:

local arr = redis.call('FT.AGGREGATE', KEYS[1], ..., 'DESC')
for i=2,(arr[1]+1) do 
    arr[i][6] = {unpack(arr[i][6], 1, ARGV[1])}
end
return arr

Kami melewati satu kunci (indeks) dan satu argumen (batas untuk produk teratas, 5 dalam kasus Anda):1 product_tags 3 .

Dengan ini, kami membatasi dampaknya hanya pada buffering, menghemat muatan jaringan, dan memuat pada klien Anda.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. socket.io redis dan kebocoran memori

  2. Bekerja dekorator @cache_page() di Django-redis-cache

  3. ruby resque tanpa memuat lingkungan rel

  4. Hubungkan ke redis dari wadah lain di buruh pelabuhan

  5. Cara yang Benar menggunakan Redis Connection Pool dengan Python