OnceDB 内存数据库引擎:像关系型数据库那样,查询、搜索、更新、全文索引海量 Redis 数据
OnceDB Node.JS by wx_15926 on 1583985442444


OnceDB 是基于 Redis 二次开发的全文搜索内存数据库。支持像 SQL 关系数据库和 NoSQL 无模式数据库那样操作数据。

Redis 是当前互联网世界最为流行高性能键值存储内存数据库。Redis 提供比较丰富的数据结构,但直接将 Redis 作为数据库还非常不方便,因此一般作为一种高速缓存工具。

为了让 Redis 能像 MySQL 或 MongoDB 数据库那样适应更多应用场景并提高开发效率。我们基于 Redis 进行了二次开发,添加了全文搜索,多条件查询,分析计算等功能。并通过辅助索引,提高在海量数据下搜索和查询的性能。

OnceDB 通过有序列表(zset)实现辅助索引,大幅提高在复杂条件查询下的搜索性能。OnceDB 并不在底层约束数据模式,数据表、字段、类型、索引等,而通过驱动层来动态定义,改变Schema 定义即可扩展现在有表和字段,从而实现模式的动态定义。

OnceDB 项目地址: http://oncedb.com

快速安装

在 Github 上选择相应操作系统和芯片架构的安装包,解压即可运行。

https://github.com/OnceDoc/OnceDB/releases/

OnceDB 并不改变 Redis 的数据存储结构,与 Redis 3.x 完全兼容,Redis 数据库文件可以直接在 OnceDB 中操作,并再返回 Redis 中使用。您可以直接将原始数据库文件附加在OnceDB中启动。 比如在 Windows 平台下,运行 oncedb-server.exe 即可启动服务。

更新数据

OnceDB 可使用 upsert 或 insert 命令添加数据,并可通过创建辅助索引来提高在大量数据下的搜索性能。OnceDB 通过操作符来自动创建这些索引,命令格式如下:

upsert schema field operator value ...

operator 即为操作符,可使用以下类型:

= 普通字段值,无索引
@ 主键,索引中存放为主键的值。 
? 分组索引
* 关键字分组索引,关键字之间使用 ',' 分隔
\ 排序索引,索引的分数权重即为字段的值

示例: 添加一条 user 数据,各字段类型如下:

var userInfo = {
    username: 'dota'    // 主键
  , password: '123456'  // 普通字段
  , title: 'SDEI'       // 创建分组索引
  , skills: 'java,go,c' // 关键字索引
}

您可以选择熟悉的第三方 Redis 客户端连接到 OnceDB,并加入命令,比如在 Redis 默认的 redis-cli 命令行中执行以下命令:

upsert user username @ dota password = 123456 title ? SDEI skills * java,go,c
> OK

这样你就成功在 user 表中添加了一条数据。“username @ dota” 代表主键字段为 username, 值为 dota。会自动创建一条 user:dota 的 hash 数据和若干辅助索引。

辅助索引以 *user 开头,使用 keys * 可查看:

oncedb_start_0.png

查询数据

可使用 find 指令查询数据,命令格式:

find schema from to field operator value ...

from to 如果是 0 -1 则代表输出所有找到的数据。

索引搜索

如果是是索引字段,可通过操作符从索引中搜索,比如搜索包含 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” 为符合条件的数据总数。

全文搜索

也可使用字符串搜索查询数据,比如搜索 skills 包含 c 的 user 数据,可使用 "~":

find user 0 -1 username = * password = * skills ~ c
1) (integer) -1
2) "user:dota"
3) "dota"
4) "123456"
5) "java,go,c"

第1行 返回的 -1 表明使用了全文搜索,除了 "~" 字符串匹配外,还支持 “<, >, <=, >=' 等数值比较搜索。 全文搜索性能较差。在有大量数据情况下,推荐使用索引搜索。

更多内容可参考: 数据修改和查询帮助文档

Node.JS 客户端

使用 node.js 客户端操作数据比通过命令行工具要简单,通过 npm 即可安装:

npm install oncedb

创建实例,连接到本地 oncedb-server:

var oncedb = require('oncedb')()

async/ await 接口

可使用 util.promisify promise 化接口,以支持 async/ await 语法: 比如 oncedb.upsert 更新数据和 oncedb.select 查询数据接口:

const util    = require('util')
const oncedb  = require('oncedb')()

const update  = util.promisify(oncedb.update).bind(oncedb)
const select  = util.promisify(oncedb.select).bind(oncedb)

定义 schema 模式

在更新查询数据前,需要先定义 schema 数据模式,指定允许接收哪些字段,设置字段类型,索引等。比如上文的 user 表,可按下面的模式定义:

oncedb.schema('user', {
    username  : 'id'
  , password  : ''
  , title     : 'index'
  , skills    : 'keywords'
});

更新数据

比如上文的更新和查询,可使用下面的代码, 此处使用同步语法,需要在 async 函数里调用:

(async () => {
  // 更新数据
  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'
  }
]

更多内容可参考: OnceDB Node.JS 客户端使用帮助

https://www.zhihu.com/question/21359049/answer/864798827 https://zhuanlan.zhihu.com/p/87682053