OnceDB 是基于 Redis 二次开发的全文搜索内存数据库,支持像 SQL 关系数据库和 NoSQL 无模式数据库那样管理数据。
OnceDB 并不改变 Redis 的数据存储结构,与 Redis 3.x 完全兼容,Redis 数据库文件可以直接在 OnceDB 中操作,并再返回 Redis 中使用。
我们一直在开发能够运行在 arm 和 x86 平台上的管理软件。很多 arm 开发板运行在 TF 存储卡中。TF 卡的读写速度其实非常有限,读取、写入速度在 10~30M/s 之间,只有 Redis 这样的内存数据库,才能够在 arm 设备持续向外传送文件时,依然保持非常优异的并发能力,而不会造成 Web 服务不可用。
Redis 中存放的只是一些基本的数据结构,只能通过复杂的方法实现数据索引、查询,所以如果只使用 Redis 数据库的话,开发效率非常低。所以一般以其它数据库为主,Redis 作为高性能缓存层来使用。
为了充分利用 Redis 优异的性能,并能像 MySQL 或 MongoDB 数据库那样适应更多应用场景并提高开发效率。我们基于 Redis 进行了二次开发,添加了全文搜索,多条件查询,分析计算等功能。并通过辅助索引,提高在海量数据下搜索和查询的性能。该项目命名为 OnceDB, 支持 Windows 和 Linux,
在 Github 上选择相应操作系统和芯片架构的安装包,解压即可运行。
https://github.com/OnceDoc/OnceDB/releases/
在 Windows 平台下,运行 oncedb-server.exe 即可启动服务。
OnceDB 通过有序列表( zset )实现辅助索引,大幅提高在复杂查询条件下,搜索海量数据的性能。
OnceDB 可使用 upsert 或 insert 命令添加数据,并通过操作符来自动创建这些索引。
比如添加一条 user:dota 数据,并设置相应索引:
@ 为 username 主键字段
? 为 title 创建分组索引
* 为 skills 创建关键字索引
命令如下
upsert user username @ dota password = 123456 title ? SDEI skills * java,go,c
> OK
然后可使用 find 指令查询数据,如果是是索引字段,可通过操作符从索引中搜索,比如搜索包含 c 关键字的 user 数据,则使用 “*” 操作符。打印 username 和 password 字段,使用 "= *" 来表达:
find user 0 -1 username = * password = * skills * c
1) (integer) 1
2) "user:dota"
3) "dota"
4) "123456"
5) "java,go,c"
搜索结果第 1 行 “(integer) 1” 为符合条件的数据总数。如果使用全文搜索,则会返回 -1。
比如全文搜索包含 c 的数据, 可使用 "~" 操作符:
find user 0 -1 username = * password = * skills ~ c
1) (integer) -1
2) "user:dota"
3) "dota"
4) "123456"
5) "java,go,c"
返回的 -1 表明使用了全文搜索,全文搜索支持 “<, >, <=, >=' 等数值比较搜索。
更多指令帮助请参考: OnceDB 数据修改和查询帮助文档
OnceDB 并不在底层约束数据模式,而通过驱动层来动态定义数据表、字段、类型、索引等,改变 Schema 定义即可扩展现在有表和字段,从而实现模式的动态定义。
OnceDB 客户端已经发布,可通过 npm 可安装:npm install oncedb
安装完成后可,连接到本地 oncedb-server:
var oncedb = require('oncedb')()
在更新查询数据前,需要先定义 schema 数据模式,指定含有哪些字段,设置字段类型,索引等。比如上文的 user 数据,可定义成如下模式:
oncedb.schema('user', {
username : 'id'
, password : ''
, title : 'index'
, skills : 'keywords'
});
然后可以通过 oncedb.upsert 更新数据。
oncedb.upsert('user', { username: 'dota', password: '123456', title: 'SDEI', skills: 'java,go,c' }, function(err) {
// done
})
然后查询数据,此时会自动根据 schema 中的定义,从相应索引查询数据。
oncedb.select('user', { skills: 'c' }, function(err, rows) {
console.log('rows.count', rows.count)
console.log(rows)
})
可使用 util.promisify 格式化接口,将回调改造成 async/ await 同步语法:
const util = require('util')
const oncedb = require('oncedb')()
const update = util.promisify(oncedb.update).bind(oncedb)
const select = util.promisify(oncedb.select).bind(oncedb)
然后上面的 callback 模式就可改写成顺序模式:
// 更新数据
await upsert('user', { username: 'dota', password: '123456', title: 'SDEI', skills: 'java,go,c' })
// 查询数据
let rows = await select('user', { skills: 'c' })
console.log('rows.count', rows.count)
console.log(rows)
输出结果:
rows.count 1
[
{
_key: 'user:dota',
skills: [ 'java', 'go', 'c' ],
username: 'dota',
password: '123456',
title: 'SDEI'
}
]
此时可根据 rows.count 来判断是不是启用了索引搜索,如果是 -1,则代表使用了全文搜索。
更多帮助请参考: OnceDB Node.JS 客户端使用帮助