OnceDB
OnceDB 动态模式内存数据库,node.js客户端驱动。
安装
npm install oncedb
快速使用
创建 oncedb 客户端实例:
var oncedb = require('oncedb')()
会自动连接到本地 oncedb-server 数据库服务。
options 选项
OnceDB 连接选项
const oncedb = OnceDB(options, cb)
Options 选项:
- host: 服务器地址
- port: [Number] 服务器端口号
- auth: oncedb-server 服务设置的密码
- select: [Number] 选中的数据库
- schema: 要装载的 schema 文件夹地址
示例
const OnceDB = require('oncedb')
const options = {
auth : '1234567890'
, select : 0
, host : '127.0.0.1'
, port : 6379
}
const oncedb = OnceDB(options);
带回调示例:
const oncedb = OnceDB(options, function(err) {
if (err {
console.log('connect error', err)
return
}
console.log('connected')
})
示例
创建了 oncedb.client 之后,就可以更新或查询数据,这是 testOnceDB.js 的示例:
var util = require('util');
var oncedb = require('oncedb')();
oncedb.schema('user', {
username : 'id'
, password : ''
, title : 'group'
, skills : 'keywords'
, birthday : 'date;sort'
})
oncedb.upsert('user', { username: 'dota', password: '123456', title: 'SDEII', skills: 'c,go,node.js', birthday: '2000-01-01' }, function(err) {
if (err) {
console.log(err)
}
})
oncedb.upsert('user', { username: 'like', password: '654321', title: 'SDEI', skills: 'javascript,node.js', birthday: '2010-12-12' }, function(err) {
if (err) {
console.log(err)
}
//When the update is complete, start the query
oncedb.select('user', { skills: 'node.js' }, function(err, rows) {
if (err) {
console.log(err)
}
console.log(rows)
})
})
运行 testOnceDB.js:
$ node testOnceDB.js
[
{
_key: 'user:dota',
skills: [ 'c', 'go', 'node.js' ],
username: 'dota',
password: '123456',
title: 'SDEII',
birthday: '2000-01-01'
},
{
_key: 'user:like',
skills: [ 'javascript', 'node.js' ],
username: 'like',
password: '654321',
title: 'SDEI',
birthday: '2010-12-12'
}
]
确保Oncedb-server服务正在运行。
Promises & async/await 语法
您可以包装 oncedb 的方法以支持 async / await 语法。 使用util.promisify方法:
const util = require('util');
const oncedb = require('oncedb')();
// promisify methods
const insert = util.promisify(oncedb.insert).bind(oncedb)
const update = util.promisify(oncedb.update).bind(oncedb)
const upsert = util.promisify(oncedb.upsert).bind(oncedb)
const select = util.promisify(oncedb.select).bind(oncedb)
const remove = util.promisify(oncedb.remove).bind(oncedb)
;(async() => {
oncedb.schema('user', {
username : 'id'
, password : ''
, title : 'group'
, skills : 'keywords'
, birthday : 'date;sort'
})
await upsert('user', { username: 'dota', password: '123456', title: 'SDEII', skills: 'c,go,node.js', birthday: '2000-01-01' })
await upsert('user', { username: 'like', password: '654321', title: 'SDEI', skills: 'javascript,node.js', birthday: '2010-12-12' })
let rows = await select('user', { skills: 'c' })
console.log(rows)
})()
运行 testOnceDB.js
$ node testOnceDB.js
rows.count 2
rows.length 1
[ { _key: 'user:dota',
skills: [ 'c', 'go', 'node.js' ],
username: 'dota',
password: '1234',
title: 'SDEII',
birthday: '2000-01-01' } ]
文档
oncedb.client
oncedb.client 是基于 node-redis 的对象,并添加了OnceDB自定义扩展命令。.
您可以在这些命令上使用 util.promisify 方法,以支持 async/ await 语法。
const util = require('util');
const oncedb = require('oncedb')();
const hgetall = util.promisify(oncedb.client.hgetall).bind(oncedb.client)
const zrange = util.promisify(oncedb.client.zrange).bind(oncedb.client)
oncedb.upsert 更新数据
更新数据,如果不存在则添加。
oncedb.upsert(schemaName, updateObject, callback)
- oncedb.insert: 插入不存在的数据
- oncedb.update: 更新现有数据
- oncedb.remove: 删除数据
options.operator
覆盖 operator
oncedb.upsert('user', { username: 'kris', password: '123456' }, function(err) {
//
}, { operator: { username: '@-' } })
会按以下命令执行:
upsert user username @- kris password = 123456
‘@-’ 不更新主键权重,更新后不影响主键排序
oncedb.select 查询数据
oncedb.select 等效于 oncedb.find,
oncedb.select(schemaName, [ where, ] callback [, options ])
oncedb.select(schemaName, where, [ options, ] callback)
where 条件:
- 相等查询: { id: 'value' }
- 包含查询: { id: { '~': 'partial string' } }
- 比较查询: { id: { '>': 10 } }
options 选项:
- from: 从0开始的行数
- to: 要结束的行数,最后一个 -1 或 (rows.count -1)
- range: 数组对象,等效于 [ from, to ]
- desc 倒序
- order / sort / between: sort / order 排序字段,你可以指定字段的分数权重范围 [ field, startScore, stopScore ]
- index: true 或 string. 将搜索结果输出到索引,在索引搜索可用
rows.count 数据总数
如果使用全文搜索: rows.count = -1 如果使用索引搜索: rows.count >= 0
;(async() => {
oncedb.schema('blog', { id: 'id;sequence', visit: 'sort' })
await upsert('blog', { visit: 10 })
await upsert('blog', { visit: 22 })
await upsert('blog', { visit: 44 })
await upsert('blog', { visit: 14 })
let blogs = await select('blog', {}, { order: [ 'visit', 10, 30 ], range: [0, 1], desc: true })
console.log('rows.count', blogs.count)
console.log(blogs)
})()
输出:
rows.count 3
[
{ _key: 'blog:2', id: '2', visit: '22' },
{ _key: 'blog:4', id: '4', visit: '14' }
]
oncedb.remove 删除数据
删除查询的数据
oncedb.remove(schemaName, where [,callback])
schema 模式定义
OnceDB中 的 Schema 类似于SQL数据库中的表。 Schema 可以指定字段类型,辅助索引类型等。
oncedb.schema(schemaName, definitions [,callback])
字段类型
字段由关键字定义。
schema: id 主键
每个模式必须只有一个ID字段。
可选参数
- 自定义索引名称
- 自定义分数权重
;(async() => {
oncedb.schema('user', {
username : 'id("users", this.ctime)'
, ctime : ''
})
await upsert('user', { username: 'dota', ctime: 123456 })
let lines = await zrange('users', 0, -1, 'withscores')
console.log(lines)
})()
结果:
[ 'dota', '123456' ]
schema: sequence 自增数字
可选参数
- prefix: 序列的前缀
- start: 开始编号
- increment: 增量数
带参数示例
;(async() => {
oncedb.schema('blog', { id: 'id;sequence("B", 1000, 10)', title: '' })
await upsert('blog', { title: 'blog 1' })
await upsert('blog', { title: 'blog 2' })
let blogs = await select('blog')
console.log(blogs)
})()
结果
[
{ _key: 'blog:B1010', id: 'B1010', title: 'blog 1' },
{ _key: 'blog:B1020', id: 'B1020', title: 'blog 2' }
]
schema: date/ datetime 日期
日期在数据库中存的是数字。
;(async() => {
oncedb.schema('user', { username: 'id', ctime: 'date' })
await upsert('user', { username: 'dota', ctime: '2000-10-10' })
await upsert('user', { username: 'hero', ctime: '2020-10-10' })
let user = await hgetall('user:dota')
let users = await select('user', { ctime: { '>': '2010-1-1' } })
console.log(user)
console.log(users)
})()
结果:
{ username: 'dota', ctime: '971136000000' }
[ { _key: 'user:hero', ctime: '2020-10-10', username: 'hero' } ]
可以使用 dateFormat 和 dateTimeformat 指定日期输出格式
oncedb.dateFormat = 'yyyy/mm/dd'
oncedb.datetimeFormat = 'yyyy/mm/dd hh:MM:ss'
let users = await select('user', {}, { from: 0, to: 0 })
console.log(users)
结果:
[ { _key: 'user:dota', username: 'dota', ctime: '2000/10/10' } ]
schema: group, index 分组索引
分组索引使用 'group' 或 'index'
;(async() => {
oncedb.schema('blog', { id: 'id;sequence', poster: 'group' })
await upsert('blog', { poster: 'dota' })
await upsert('blog', { poster: 'hero' })
await upsert('blog', { poster: 'dota' })
let blogs = await select('blog', { poster: 'dota' })
console.log(blogs)
})()
结果:
[
{ _key: 'blog:1', poster: 'dota', id: '1' },
{ _key: 'blog:3', poster: 'dota', id: '3' }
]
默认分组索引名称格式: *schema.field:value
let lines = await zrange('*blog.poster:dota', 0, -1)
console.log(lines)
> [ '1', '3' ]
可选参数
- 自定义索引名称
- 自定义分数权重
oncedb.schema('blog', { id: 'id;sequence', poster: 'group("blog_user", Date.now())' })
schema: keywords, groups 关键字索引
关键字索引:使用 “keywords” 或 “groups” 用逗号或数组对象分隔关键字:
;(async() => {
oncedb.schema('blog', { id: 'id;sequence', keys: 'keywords' })
await upsert('blog', { keys: 'node.js,c,go' })
await upsert('blog', { keys: [ 'go', 'c' ] })
await upsert('blog', { keys: 'node.js,c' })
// select data which has go and c
let blogs = await select('blog', { keys: ['go', 'c'] })
console.log(blogs)
})()
结果:
[
{ _key: 'blog:1', keys: [ 'node.js', 'c', 'go' ], id: '1' },
{ _key: 'blog:2', keys: [ 'go', 'c' ], id: '2' }
]
可选参数
- 自定义索引名称
- 自定义分数权重
oncedb.schema('blog', { id: 'id', keys: 'keywords("blog_keys", Date.now())' })
schema: sort, order 排序索引
排序索引使用 "sort" 或 "order"
;(async() => {
oncedb.schema('blog', { id: 'id;sequence', visit: 'sort' })
await upsert('blog', { visit: 10 })
await upsert('blog', { visit: 22 })
await upsert('blog', { visit: 44 })
await upsert('blog', { visit: 14 })
let blogs = await select('blog', {}, { order: [ 'visit', 10, 20 ] })
console.log(blogs)
})()
结果:
[
{ _key: 'blog:1', id: '1', visit: '10' },
{ _key: 'blog:4', id: '4', visit: '14' }
]
可选参数
- 自定义索引名称
其它关键字
schema: required
schema: int
schema: number
schema: array, json, object
schema: min (minNumber)
schema: max (maxNumber)
schema: minlen (minLength)
schema: maxlen (maxLength)
oncedb.extend 扩展
扩展现有 schema.
连接查询
可以用数组实现连接查询
oncedb.select(schemaName, [query1, query2 ...], options, cb)
oncedb.select(schemaName, [[query1, options1], [query2, options2] ...], options, cb)
示例
oncedb.schema('issue', { id:'id;sequence', group:'index', keys:'keywords', priority:'sort' })
await upsert('issue', { group: 'bug', keys: 'node.js,c,go', priority: 1 })
await upsert('issue', { group: 'task', keys: 'java,c,go', priority: 7 })
await upsert('issue', { group: 'task', keys: 'java,c', priority: 4 })
合并查询两个条件:返回3行数据
var issues = await select('issue', [ { group: 'task'}, { priority: 1 } ])
合并带有参数的查询:返回2行数据
var issues = await select('issue', [
[ { group: 'task'}, { between: [ 'priority', 7, 10 ] } ]
, { keys: 'node.js' }
])
事件
ready
oncedb.on('ready', function() {
console.log('ready')
})
error
oncedb.on('error', function(err) {
console.log('error', err)
})
connect
oncedb.on('connect', function(err) {
console.log('connect')
})
oncedb.client 扩展指令
参考: OnceDB 指令参考