OnceDB更新:在Redis中实现SQL数据库的多条件关联查询,内、外连接合并索引搜索使用教程
OnceDB 是基于 Redis 二次开发的全文搜索内存数据库,支持像 SQL 关系数据库和 NoSQL 无模式数据库那样管理数据。
条件查询
在 OnceDB 的 node.js 驱动中,可直接使用类似 mongodb 的查询语法,来查询 redis 数据库:
oncedb.select(schemaName, query, options, callback)
示例,准备测试数据:
(async() => {
const util = require('util')
const oncedb = require('oncedb')()
// priomise 化接口,使用顺序语法执行异步函数
const upsert = util.promisify(oncedb.upsert).bind(oncedb)
const select = util.promisify(oncedb.select).bind(oncedb)
const zrange = util.promisify(oncedb.client.zrange).bind(oncedb.client)
oncedb.client.flushdb()
// 定义blog: id 自增ID, user 分组索引, keys 关键字索引, visit 排序索引
oncedb.schema('blog', { id: 'id;sequence', user: 'group', keys: 'keywords', visit: 'sort' })
// 添加测试数据
await upsert('blog', { user: 'fire', keys: 'c,java,js', visit: 3899 })
await upsert('blog', { user: 'fire', keys: 'go,c,js', visit: 1000 })
await upsert('blog', { user: 'like', keys: 'java,c,node.js', visit: 1200 })
await upsert('blog', { user: 'like', keys: 'node.js,go,c', visit: 3206 })
await upsert('blog', { user: 'mind', keys: 'js,go,c', visit: 2106 })
await upsert('blog', { user: 'fire', keys: 'java,js,go,c', visit: 9999 })
})();
多条件查询, { user: 'fire', keys: 'c' }, 并且 visit 在 1000 和 4000 之间的数据:
var rows = await select('blog', { user: 'fire', keys: 'c' }, { sort: [ 'visit', 1000, 4000 ] })
console.log(rows)
输出结果:
[
{
_key: 'blog:2',
id: '2',
user: 'fire',
keys: [ 'go', 'c', 'js' ],
visit: '1000'
},
{
_key: 'blog:1',
id: '1',
user: 'fire',
keys: [ 'c', 'java', 'js' ],
visit: '3899'
}
]
连接查询
OnceDB 最新版添加了连接查询的功能,可以用数组实现多条件连接查询.
多条件查询的前提是搜索的字段在 schema 中都被定义成了索引,这样在 OnceDB 中可以通过一系列的交集和并集运算来提取数据,语法如下:
oncedb.select ([query1, query2 ...], options, cb)
或
oncedb.select ([[query1, options1], [query2, options2] ...], options, cb)
比如当两个搜索条件求其合集,并按 visit 排序:
var rows = await select('blog', [
[{ user: 'fire', keys: 'c' }, { sort: [ 'visit', 1000, 4000 ] }]
, [{ user: 'like', keys: 'java' }, { sort: 'visit' }]
])
console.log(rows)
输出结果:
[
{
_key: 'blog:2',
_score: 1000,
id: '2',
user: 'fire',
keys: [ 'go', 'c', 'js' ],
visit: '1000'
},
{
_key: 'blog:3',
_score: 1200,
id: '3',
user: 'like',
keys: [ 'java', 'c', 'node.js' ],
visit: '1200'
},
{
_key: 'blog:1',
_score: 3899,
id: '1',
user: 'fire',
keys: [ 'c', 'java', 'js' ],
visit: '3899'
}
]
保存索引
多条件联连查询是通过索引并集实现的,可通过 index 参数只输出索引,然后通过 OnceDB 的 zrangehmget 指令来提取数据,而不必每次都重新进行计算,这样能提高在海量数量下的性能:
比如,上文的例子通过 { index: 'blog_union' }) 保存在 blog_union 索引中:
var indexName = await select('blog', [
[{ user: 'fire', keys: 'c' }, { sort: [ 'visit', 1000, 4000 ] }]
, [{ user: 'like', keys: 'java' }, { sort: 'visit' }]
], { index: 'blog_union' })
打印索引内容:
var lines = await zrange(indexName, 0, -1)
console.log(lines)
输出:
[ '2', '3', '1' ]
使用 zrangehmget 指令,从索引中输出对应的hash数据:
首先 promise 化 zrangehmget 接口:
const zrangehmget = util.promisify(oncedb.client.zrangehmget).bind(oncedb.client)
查询从 1 到 1 的第2条数据(从零开始)
var rows = await zrangehmget('blog_union', 1, 1, 'blog: user keys visit')
console.log(rows)
输出结果:
[
{
_key: 'blog:3',
_score: 1200,
user: 'like',
keys: 'java,c,node.js',
visit: '1200'
}
]
参考资料:
zrangehmget指令使用可参考 搜索、查询、计算、求和指令
Node.JS客户端文档 OnceDB 客户端使用帮助