[REDIS] 각 그룹의 Redisearch 집계 반환 상위 5
REDIS각 그룹의 Redisearch 집계 반환 상위 5
나는이 형식의 문서가 있다고 가정 :
product_name TEXT tags TAG score NUMERIC
[product1, [tag1, tag2, tag3], 10]
[product2, [tag2, tag3, tag4], 100]
....
나는 제품의 점수 중 가장 높은 금액 순으로 태그를 반환하는 쿼리와 각 태그에 대한 제품의 상위 5 개 원하는 :
[tag3, 110, [product2, product 1]]
[tag2, 110, [product2, product 1]]
[tag4, 100, [product2]]
[tag1, 10, [product 1]]
내가 지금까지 (각 태그에 대해 반복) 개별적으로 각 제품 / 태그 키를 저장하는 것을 각각의 제품에 대한 우리는 각 태그에 대해 하나의 별도의 문서를 가지고 있으며 ID는 제품 이름과 태그 조합 : 제품 _ TEXT 태그 TAG 점수 숫자. 지금은 상위 태그의 목록을 가져 집계 쿼리를 실행할 수 있습니다 :
FT.AGGREGATE product_tags *
GROUP BY 1 @TAG
REDUCE SUM 1 @score as total_score
SORT BY 2 @total_score DESC
이 순서대로 나에게 상위 태그를 제공하지만 난 내가 찾은 각 태그에 대한 상위 5 개 제품을 얻으려면 TOLIST 모든 제품이 정렬되지 반환 한 @product_name을 줄이기에만 존재하고 @score BY FIRST_VALUE 4 @product_name을 줄이려면이됩니다 첫 번째 최고 제품을 반환합니다 DESC.
의 하나 개의 쿼리에서 각 태그에 대한 상위 5 개 제품을 가정 해 봅시다 얻을 방법이 있나요. 없는 경우에는 문서 저장 형식을 변경 (또는 추가를 추가) 가능한 한 적은 쿼리로 쿼리 수의 또는이 종류를 만들 수있는 방법으로 할 수 있습니다?
문제가되지해야하지만 파이썬 Redisearch 클라이언트를 사용하고 있습니다.
해결법
-
==============================
1.먼저:
먼저:
여기에 내가 시험에 사용되는 스키마는 다음과 같습니다
FT.CREATE product_tags NOOFFSETS NOHL NOFREQS STOPWORDS 0 SCHEMA product_name TEXT tags TAG score NUMERIC SORTABLE
당신은 파이프 라인으로 FT.AGGREGATE 생각합니다.
첫 번째 단계는 우리가 TOLIST 1 @product_name을 줄이려 할 때 나중에, 아래로 파이프 라인의 것을, 목록 정렬 나온다 그래서, @score으로 제품을 분류하는 것입니다 :
SORTBY 2 @score DESC
나는 당신이 이미 TAG 필드가 다른 제품 당 전체 쉼표로 구분 된 문자열 태그 목록에 의해 그룹화하는 것처럼, 태그를 다루는 적용 / LOAD을하고있다 생각합니다. 태그 필드 문제에 GROUPBY 허용을 참조하십시오. 파이프 라인은 그렇게 우리의 다음 단계입니다 :
LOAD 1 @tags APPLY split(@tags) as TAG
우리 @TAG하여 다음 그룹 및 두 감축을 적용합니다. 우리의 제품 목록 정렬 나올 것입니다.
GROUPBY 1 @TAG REDUCE SUM 1 @score AS total_score REDUCE TOLIST 1 @product_name AS products
마지막으로, 일종의 우리 @total_score의 :
SORTBY 2 @total_score DESC
명령의 최종보기 여기 :
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
결과를 설명하기 위해 명령의 전체 목록은 여기. 나는 쉽게 제품의 분류 시각적으로 확인하기 위해 점수 XX와 productXX을 사용했다.
> 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"
당신은 우리가 가격을 지불,이 차이가 없습니다뿐만 아니라 상위 5 복잡성이 많다는, 제품의 전체 목록이 정렬지고있다. 영향은 버퍼링, 네트워크 페이로드 및 클라이언트입니다.
당신은 루아 스크립트를 사용하여 5 맨 위로 제한 할 수 있습니다 :
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
루아 스크립트 위의 여기에 친절한보기 :
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
1 product_tags 3 : 우리는 (귀하의 경우 상위 제품에 대한 제한, 5) 하나의 키 (인덱스)와 하나 개의 인수를 전달하고 있습니다.
이, 우리는 클라이언트에만 저장 네트워크 페이로드 및로드 버퍼링에 미치는 영향을 제한했다.
from https://stackoverflow.com/questions/59530799/redisearch-aggregate-return-top-5-of-each-group by cc-by-sa and MIT license
'REDIS' 카테고리의 다른 글
[REDIS] Node.js를을 사용하여 클러스터 ElastiCache에 연결하는 방법 (0) | 2020.01.18 |
---|---|
[REDIS] Predis에서 MATCH 옵션 SCAN을 사용하는 방법 (0) | 2020.01.18 |
[REDIS] 레디 스 KEYSPACE 알림 flushdb와 (0) | 2020.01.18 |
[REDIS] 클러스터 지속적으로 로그 WSA_IO_PENDING를 인쇄 레디 스 (0) | 2020.01.18 |
[REDIS] 레디 스에서 해시의 배열을 저장하는 방법 (0) | 2020.01.18 |