OnceDB: use full-text search, string search, multi-condition query, numerical comparison search, index search in Redis


Poster Kris Zhang  Post time 1580550658871
Keywords OnceDB 

OnceDB is a full-text search database based on Redis. It can create auxiliary indexes like SQL databases, simplify searching and improve search performance. OnceDB does not change the data storage structure of Redis. Redis database files can be directly operated in OnceDB and then returned to Redis for use.

Full text search

OnceDB supports direct search, supports objects such as String and Hash,

Search string: search pattern operator value

Use the SEARCH command

# Create data
set test1 'this is testing'
> OK
set test2 'this is article'
> OK

# Search data
search test* ~ article
1) test1
2) this is testing
3) test2
4) this is article

Operator supports:

= Exact match
~ Partial match
> >= < <= Compare match

Search hash: hsearch pattern field operator value ...

Use the hsearch command

There is no concept of "table" in redis. Generally, the key name using schema:id includes the table name and the primary key. For example, user:001 is a hash object with a user table and a primary key value of 001.

# Create hash data
hmset user:001 name kris email c2u@live.cn gender male age 16
> OK
hmset user:002 name sunny age 24
> OK

# Search hash data
hsearch user:* age > 18 name = *
1) user:002
2) 24
3) sunny

Search ordered list(zset): zhsearch key from to schema field operator value ...

Use test:* or user:* pattern matching directly, because it will traverse all the keys, and the performance is low. zhsearch can search the corresponding primary key in an ordered list and specify the search scope.

In the above example, we store the primary key value of user into the *user ordered list, and the score is an integer about time

zadd *user 20020201 001 20020202 002

Search for the first matching data (from 0 to 0)

zhsearch *user 0 0 user: age > 10
1) -1
2) user:001
3) 16

When using full-text search, the first parameter returned is always -1.

Index search

Create index

The performance of full-text search is poor. You can improve the performance by creating indexes. The method is to create ordered lists for the indexed fields, and then perform an intersection query operation on these ordered lists when the conditional query is performed.

# Create hash data
hmset article:001 poster dota visit 21 key js
hmset article:002 poster dota visit 11 key c
hmset article:003 poster like visit 34 key js
hmset article:004 poster like visit 44 key c

Then we create indexes for the above fields, the weight score is set to: 202000201, an integer about time, the value is the ID value of article

# Create indexed
zadd *article.poster:dota 20200201 001 20200201 002
zadd *article.poster:like 20200201 003 20200201 004
zadd *article.key:js 20200201 001 20200201 003
zadd *article.key:c 20200201 002 20200201 004
# "visit" using its value as the weight score
zadd *article.visit 21 001 11 002 34 003 44 004

Query by index

Find the intersection of the two indexes *article.key:js and *article.poster:dota and store them in the *tmp1 ordered list:

zinterstore *tmp1 2 *article.key:js *article.poster:dota
> 1

Then *tmp1 stores the ID set that meets the key = js and poster = dota conditions:

zrange *tmp1 0 -1
> 001

You can use the zrangehmget command to print the corresponding HASH value:

zrangehmget *tmp1 0 -1 article: key poster
1) 001
2) 40400402
3) js
4) dota
5) 
6) 

The result is the same as the direct full-text search key = js and poster = dota

hsearch article:* key = js poster = dota
1) article:001
2) js
3) dota

Search range

For example, to search for data with the number of visits between 20 and 30, and key = js, you can achieve it by controlling the weight

Create a temporary index, only take the weight of *article.visit and the data of key = js

zinterstore *tmp2 2 *article.key:js *article.visit weights 0 1
> 2

Take data between 20 and 30

zrangebyscore *tmp2 20 30
> 001

You can use zrangehmgetbyscore to print the corresponding hash data:

zrangehmgetbyscore *tmp2 20 30 article: key visit
1) 001
2) 21
3) js
4) 21
5) 
6) 

The results are consistent with those using full-text search:

hsearch article:* visit >= 20 visit <= 30 key = js
1) article:001
2) 21
3) 
4) js

Because there are two identical fields, visit> = 20 visit <= 30, the search results will only output one, and the repeated fields in the third row will output empty.

More OnceDB extended instructions can be viewed: Search, query, calculate, and sum instructions in OnceDB

Automatic indexing

The creation and maintenance of Redis indexes is not very convenient. OnceDB can choose to automatically create auxiliary indexes when data is modified.

Create index:upsert schema field operator value ...

Use upsert / insert / update directives and special operators to create indexes automatically:

The example above can be written as:

upsert article id @ 001 poster ? dota visit / 21 key ? js
upsert article id @ 002 poster ? dota visit / 11 key ? c
upsert article id @ 003 poster ? like visit / 34 key ? js
upsert article id @ 004 poster ? like visit / 44 key ? c

Operator:

@: Primary key ?: Group index /: Sort index

The indexes are automatically created after the operation: *article *article.poster:dota *article.poster:like *article.visit *article.key:js *article.key:c

Multi-condition index query:find schema from to field operator value ...

For fields with indexes, you can use the find command to query through the index fields. For example, query: data of key = js and poster = dota. You can use "?" To indicate that these two fields are grouped indexes:

find article 0 -1 key ? js poster ? dota
1) 1
2) article:001
3) js
4) dota

1 represents the total amount of data. If it is -1, it means that full-text search is used, and the performance is poor.

Index range query

You can add @ to specify an index range and use + to specify which index field to use for the score weight range.

find article 0@20 -1@30 key ? js visit /+ *
1) 1
2) article:001
3) js
4) 21

Delete index

OnceDB does not store index definitions. When deleting, you need to manually indicate which fields contain indexes. You need to specify the field names and index operators.

remove article @ 001 key ? poster ? visit /

You can also customize the index name and weight score. For more instructions, please see: OnceDB data modification and query help documentation





Reply (0)
  • #
 Keywords
OnceDB