sql >> Database >  >> NoSQL >> Redis

Opnieuw zoeken verzamelde top 5 van elke groep

Ten eerste:

  • Zorg ervoor dat u functies uitschakelt die u niet gebruikt (NOOFFSETS , NOHL ,NOFREQS , STOPWORDS 0 )
  • Gebruik SORTABLE voor uw NUMERIC score .

Hier is het schema dat ik heb gebruikt om te testen:

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

U wilt denken aan FT.AGGREGATE als een pijplijn.

De eerste stap zal zijn om de producten te sorteren op @score, zodat we later, in de pijplijn, wanneer we REDUCE TOLIST 1 @product_name , de lijst wordt gesorteerd weergegeven:

SORTBY 2 @score DESC

Ik denk dat je al bezig bent met LOAD /APPLY om met de tags om te gaan, als TAG velden zouden anders worden gegroepeerd op de volledige door komma's gescheiden string-tags-lijst, per product. Zie GROUPBY toestaan ​​bij probleem met tagvelden. Dus onze volgende stap zit in de pijplijn:

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

We groeperen vervolgens op @TAG en passen de twee kortingen toe. Onze productenlijst wordt gesorteerd weergegeven.

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

Ten slotte sorteren we op @total_score :

SORTBY 2 @total_score DESC

Hier een laatste weergave van de opdracht:

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

Hier een volledige lijst met opdrachten om het resultaat te illustreren. Ik gebruikte productXX met score XX om de sortering van producten gemakkelijk visueel te controleren.

> 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"

U krijgt de volledige lijst met gesorteerde producten, niet alleen de top 5. Qua complexiteit maakt het geen verschil, wij hebben de prijs betaald. De impact zit in buffering, netwerkbelasting en uw klant.

Je kunt de top 5 beperken met een Lua-script:

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

Hier een vriendelijke weergave van het Lua-script hierboven:

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

We geven één sleutel door (de index) en één argument (de limiet voor topproducten, 5 in jouw geval):1 product_tags 3 .

Hiermee hebben we de impact beperkt tot alleen bufferen, opgeslagen netwerkpayload en belasting op uw client.




  1. Hoe voeg ik een document met datum in Mongo in?

  2. Wanneer moet u Transparent Huge Pages uitschakelen voor redis

  3. Voeg een string toe aan het einde van een bestaand veld in MongoDB

  4. Mongo Query met Regex in Node JS werkend OP EEN VARIABELE