Ten eerste:
- Zorg ervoor dat u functies uitschakelt die u niet gebruikt (
NOOFFSETS
,NOHL
,NOFREQS
,STOPWORDS 0
) - Gebruik
SORTABLE
voor uwNUMERIC
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.