doublesharp
doublesharp

Reputation: 27607

Redis Lexicographical Range Search Inconsistent Results

I am trying to do a lexicographical range search on a Redis sorted set, but getting inconsistent results based on my understanding of how this feature works. The results are similar when using ZRANGECOUNT, ZRANGEBYLEX, and ZREMRANGEBYLEX.

Working Queries

This is an example of my set with 3 elements just using ZRANGE.

redis> ZRANGE myset 0 -1 
0  00000000022xm26hax001
1  00000000022xm26hax002
2  00000000022xm26hax003

I can also get all of the elements lexicographically.

redis> ZRANGEBYLEX myset - +
0  00000000022xm26hax001
1  00000000022xm26hax002
2  00000000022xm26hax003

Doing a range search by leaving off the last 3 characters also works as expected.

redis> ZRANGEBYLEX myset [00000000022xm26hax [00000000022xm26hax\xff
0  00000000022xm26hax001
1  00000000022xm26hax002
2  00000000022xm26hax003

Adjusting the range arguments I can select just the first two elements as well.

redis> ZRANGEBYLEX myset [00000000022xm26hax001 [00000000022xm26hax002\xff
0  00000000022xm26hax001
1  00000000022xm26hax002

A short start seems to be acceptable:

redis> ZRANGEBYLEX myset [00000000022x [00000000022xm26hax001\xff
0  00000000022xm26hax001

Problem Queries

I run into problems however when I try to select using a shorter version of the string - these all return 0 results when I would expect them to return 3.

ZRANGEBYLEX myset [00000000022xm26h [00000000022xm26h\xff
ZRANGEBYLEX myset [00000000022x [00000000022x\xff

But then adding back just the "m" makes it return all three elements again.

redis> ZRANGEBYLEX myset [00000000022xm [00000000022xm\xff
0  00000000022xm26hax001
1  00000000022xm26hax002
2  00000000022xm26hax003

Can someone explain this behavior? What is the correct way to get back all elements that start with "00000000022x" given my example dataset?

Why does ZRANGEBYLEX myset [00000000022x [00000000022x\xff return no results but ZRANGEBYLEX myset [00000000022xm [00000000022xm\xff returns all the results - just adding the "m" seems to make it work as expected?

Upvotes: 1

Views: 279

Answers (2)

doublesharp
doublesharp

Reputation: 27607

The solution to this could ultimately not be determined by the question I posted. For clarity I left out the score of each sorted set entry which was meant to be an expiration timestamp. Unfortunately the documentation for ZRANGEBYLEX says:

When all the elements in a sorted set are inserted with the same score, in order to force lexicographical ordering, this command returns all the elements in the sorted set at key with a value between min and max.

My entries did not have the same score so they were not being sorted lexicographically.

Upvotes: 0

Łukasz Langa
Łukasz Langa

Reputation: 31

If you would like Redis to resolve escape codes in your strings (like the \xff in your examples), you need to wrap the strings in quotation marks.

In other words, this will treat \xff as byte 255:

127.0.0.1:6379> ZRANGEBYLEX myset [00000000022xm26hax001 "[00000000022xm26ha\xff"
1) "00000000022xm26hax001"
2) "00000000022xm26hax002"
3) "00000000022xm26hax003"

Whereas this treats \xff as four bytes (92, 120, 102, 102):

127.0.0.1:6379> ZRANGEBYLEX myset [00000000022xm26hax001 [00000000022xm26ha\xff
(empty list or set)

This explains your confusing results.

Upvotes: 1

Related Questions