Redisearch: How to apply multiple sorting

Created on 11 Dec 2017  路  5Comments  路  Source: RediSearch/RediSearch

I am having a requirement where I need to fetch some records sorted by more than 1 fields.

But, It seems like I can apply sorting on one field only.

"FT.SEARCH" "VVV" "Seq_l:[179910,179920]" NOCONTENT SORTBY Month ASC Name ASC LIMIT 0 25

"FT.SEARCH" "VVV" "Seq_l:[179910,179920]" NOCONTENT SORTBY Month ASC SORTBY Name ASC LIMIT 0 25

Is there any workaround for this?

Most helpful comment

This will actually be possible soon via the aggregations API and we'll get to it with the sorting API as well.

All 5 comments

Not at the moment, sorry!

We have use cases for this as well.

As a workaround, we will add extra manual 'multisort' TEXT fields to the document, NOINDEX and SORTABLE.
We will serialize all values manually into those 'multisort' fields.
For descending index parts, we'll do an 'inverse' (MAXINT-n for integer values, and 0xFF-asc(c) byte for byte in strings. I will strip higher ascii before inverting, to avoid inadvertently creating tokenization characters).
Should work, I'll let you know how it goes (if anyone sees a problem with this simple workaround, please let me know).

Here's a full example of the feature request "Support multiple SORTBY fields in FT.SEARCH":

FT.CREATE "ftFoo" SCHEMA first NUMERIC SORTABLE second NUMERIC SORTABLE third NUMERIC SORTABLE

FT.ADD ftFoo 1_1_1 1.0 FIELDS first 1 second 1 third 1
FT.ADD ftFoo 1_3_1 1.0 FIELDS first 1 second 3 third 1
FT.ADD ftFoo 1_2_1 1.0 FIELDS first 1 second 2 third 1
FT.ADD ftFoo 3_1_1 1.0 FIELDS first 3 second 1 third 1
FT.ADD ftFoo 3_1_2 1.0 FIELDS first 3 second 1 third 2
FT.ADD ftFoo 3_1_3 1.0 FIELDS first 3 second 1 third 3
FT.ADD ftFoo 1_1_3 1.0 FIELDS first 1 second 1 third 3
FT.ADD ftFoo 1_0_3 1.0 FIELDS first 1 second 0 third 3

FT.SEARCH ftFoo '@first:[1 3]' NOCONTENT SORTBY first DESC SORTBY third DESC SORTBY second ASC

RediSearch 1.0.2 output:

1) (integer) 8
2) "3_1_1"
3) "3_1_2"
4) "3_1_3"
5) "1_1_3"
6) "1_0_3"
7) "1_3_1"
8) "1_2_1"
9) "1_1_1"

Desired output:

1) (integer) 8
2) "3_1_3"
3) "3_1_2"
4) "3_1_1"
5) "1_0_3"
6) "1_1_3"
7) "1_1_1"
8) "1_2_1"
9) "1_3_1"

FYI:
@dvirsky In a first usecase, I didn't need the more complex serialization nor inversion yet (as mentioned above).
I could suffice with a simple ((A*10000000)+B) in a custom NUMERIC multisort field (A + B = compound index, aka multisort), and use the DESC modifier in FT.SEARCH. The maximum precision of 24 bits wasn't an issue for this usecase (but might be for other usecases).

This workaround works fine.

This will actually be possible soon via the aggregations API and we'll get to it with the sorting API as well.

This now exists in aggregations.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

chuckyz picture chuckyz  路  9Comments

eitanshapiro picture eitanshapiro  路  5Comments

cit68 picture cit68  路  8Comments

dme-development picture dme-development  路  8Comments

drittich picture drittich  路  11Comments