Erstens:
- Deaktivieren Sie Funktionen, die Sie nicht verwenden (
NOOFFSETS
,NOHL
,NOFREQS
,STOPWORDS 0
) - Verwenden Sie
SORTABLE
für IhrenNUMERIC
score
.
Hier ist das Schema, das ich zum Testen verwendet habe:
FT.CREATE product_tags NOOFFSETS NOHL NOFREQS STOPWORDS 0
SCHEMA product_name TEXT tags TAG score NUMERIC SORTABLE
Sie möchten an FT.AGGREGATE
denken als Pipeline.
Der erste Schritt besteht darin, die Produkte nach @score zu sortieren, damit sie später, unten in der Pipeline, wenn wir REDUCE TOLIST 1 @product_name
, die Liste wird sortiert ausgegeben:
SORTBY 2 @score DESC
Ich denke, Sie machen bereits LOAD
/APPLY
um mit den Tags umzugehen, als TAG
Felder würden andernfalls nach der vollständigen, durch Kommas getrennten String-Tags-Liste pro Produkt gruppiert. Siehe Problem GROUPBY für Tag-Felder zulassen. Unser nächster Schritt ist also in der Pipeline:
LOAD 1 @tags
APPLY split(@tags) as TAG
Wir gruppieren dann nach @TAG und wenden die beiden Reduzierungen an. Unsere Produktliste wird sortiert ausgegeben.
GROUPBY 1 @TAG
REDUCE SUM 1 @score AS total_score
REDUCE TOLIST 1 @product_name AS products
Schließlich sortieren wir nach @total_score
:
SORTBY 2 @total_score DESC
Hier eine letzte Ansicht des Befehls:
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 eine vollständige Liste der Befehle zur Veranschaulichung des Ergebnisses. Ich habe productXX
verwendet mit Punktzahl XX
zur einfachen visuellen Überprüfung der Sortierung von Produkten.
> 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"
Sie erhalten die vollständige Liste der sortierten Produkte, nicht nur die Top 5. In Bezug auf die Komplexität spielt es keine Rolle, wir haben den Preis bezahlt. Die Auswirkungen liegen in der Pufferung, der Netzwerknutzlast und Ihrem Client.
Sie können mit einem Lua-Skript auf die Top 5 beschränken:
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 eine freundliche Ansicht des obigen Lua-Skripts:
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
Wir übergeben einen Schlüssel (den Index) und ein Argument (das Limit für Top-Produkte, in Ihrem Fall 5):1 product_tags 3
.
Damit haben wir die Auswirkungen auf das Puffern beschränkt, Netzwerknutzlast eingespart und Ihren Client belastet.