OnceDB http://oncedb.com/ 是基于 Redis 实现的全文搜索数据库, 可以像 SQL 数据库那样创建辅助索引, 提高条件搜索的性能.
OnceDB 并不改变 Redis 的数据存储结构, Redis 数据库文件可以直接在 OnceDB 中操作, 然后再返回 Redis 中使用.
项目地址: http://oncedb.com/
全文搜索
OnceDB 提供直接搜索指令, 支持 String 和 Hash 等对象,
搜索 String: search pattern operator value
搜索 String 类型的键, 可使用 search
- # 创建数据
- set test1 'this is testing'
- > OK
- set test2 'this is article'
- > OK
- # 搜索数据
- search test* ~ article
- 1) test1
- 2) this is testing
- 3) test2
- 4) this is article
operator 操作符支持: = 完全匹配 ~ 部分匹配 >>= <<= 比较匹配
搜索 Hash: hsearch pattern field operator value ...
hsearch 可以实现对 Hash 对象的搜索.
在 Redis 中没有表的概念, 一般使用 schema:id 的键名包含表名和主键. 比如 user:001 为 user 表, 主键值为 001 的 Hash 对象.
- # 创建 Hash 数据
- hmset user:001 name kris email c2u@live.cn gender male age 16
- > OK
- hmset user:002 name sunny age 24
- > OK
- # 搜索 Hash 数据
- hsearch user:* age> 18 name = *
- 1) user:002
- 2) 24
- 3) sunny
搜索 ZSET: zhsearch key from to schema field operator value ...
直接使用 test* 或 use:* 模式匹配, 因为会遍历所有的键, 性能低下. zhsearch 可以在有序列表中搜索对应主键, 并指定搜索范围.
在上例中, 我们将 user 的主键值存放到 *user 有序列表中, 分数为一个关于时间的整数
zadd *user 20020201 001 20020202 002
搜索第一条匹配的数据 (从 0 到 0)
- zhsearch *user 0 0 user: age> 10
- 1) -1
- 2) user:001
- 3) 16
使用全文搜索时, 第一个返回的参数始终是 -1.
索引搜索
搜索原理
全文搜索的性能比较差, 可通过创建索引的办法提高性能, 办法是为索引字段创建一个有序列表, 然后在条件查询时, 对这些有序列表做交集查询操作.
- # 创建 4 条 Hash 数据
- 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
然后我们为上面的字段创建索引, 权重分数设为: 202000201, 一个关于时间的整数, 值为 article 的 ID 值
- # 维护索引
- 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 的索引直接使用其值为权重分数
- zadd *article.visit 21 001 11 002 34 003 44 004
按索引查询
求 *article.key:JS 和 *article.poster:dota 两个索引的交集, 并存放在 *tmp1 有序列表中:
- zinterstore *tmp1 2 *article.key:JS *article.poster:dota
- > 1
然后 *tmp1 存放的就是 满足 key = JS 和 poster = dota 条件的 ID 集合:
- zrange *tmp1 0 -1
- > 001
可使用 zrangehmget 指令打印相应的 HASH 值:
- zrangehmget *tmp1 0 -1 article: key poster
- 1) 001
- 2) 40400402
- 3) JS
- 4) dota
- 5)
- 6)
其结果与直接全文搜索 key = JS 和 poster = dota 的搜索结果相同
- hsearch article:* key = JS poster = dota
- 1) article:001
- 2) JS
- 3) dota
搜索范围
比如要搜索 visit 数量在 20 到 30 之间, key = JS 的数据, 可通过控制权重的方法实现
创建临时索引, 只取 *article.visit 的权重 和 key = JS 的数据
- zinterstore *tmp2 2 *article.key:JS *article.visit weights 0 1
- > 2
取 20 ~ 30 之间的数据
- zrangebyscore *tmp2 20 30
- > 001
可使用 zrangehmgetbyscore 打印出对应的 hash 数据:
- zrangehmgetbyscore *tmp2 20 30 article: key visit
- 1) 001
- 2) 21
- 3) JS
- 4) 21
- 5)
- 6)
其结果与使用全文搜索的结果一致:
- hsearch article:* visit>= 20 visit <= 30 key = JS
- 1) article:001
- 2) 21
- 3)
- 4) JS
因为里面有两个相同的字段, visit>= 20 visit <= 30, 搜索结果只会输出一个, 第 3 行重复的字段会输出空.
OnceDB 更多扩展指令可查看: OnceDB 搜索, 查询, 计算, 求和指令
自动索引
Redis 索引的创建和维护并不十分方便, OnceDB 在数据修改时可选择自动创建辅助索引.
创建索引: upsert schema field operator value ...
使用 upsert/insert/update 指令和特殊的操作符可自动创建索引:
如上文的例子可写成:
- 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
操作符:
@ : 主键
? : 分组索引
/ : 排序索引
操作后会自动创建: *article *article.poster:dota *article.poster:like *article.visit *article.key:JS *article.key:c 等索引.
多条件索引查询: find schema from to field operator value ...
含有索引的字段, 可使用 find 命令通过索引字段查询出来, 比如查询: key = JS 和 poster = dota 的数据, 可通过 "?" 指明这两个字段是分组索引:
- find article 0 -1 key ? JS poster ? dota
- 1) 1
- 2) article:001
- 3) JS
- 4) dota
1: 代表符合条件的数据总数, 如果是 -1 则代表使用了全文搜索, 性能较差.
索引范围查询
可添加 @ 指定索引范围, 并使用 + 指定使用哪个索引字段的分数权重范围.
- find article 0@20 -1@30 key ? JS visit /+ *
- 1) 1
- 2) article:001
- 3) JS
- 4) 21
删除自动索引
OnceDB 不存储索引定义, 删除时需要手动指出哪些字段含有索引, 需要指定字段名和索引操作符即可.
remove article @ 001 key ? poster ? visit /
还可以自定义索引名称, 权重分数, 更多说明可查看: OnceDB 数据修改和查询帮助文档
来源: http://www.tuicool.com/articles/vmmAZrZ