OnceDB 更新:在 Redis 中实现 SQL 数据库的多条件关联查询,内、外连接合并索引搜索使用教程

2020-03-12 09:18:05 +08:00
 newghost

OnceDB 是基于 Redis 二次开发的全文搜索内存数据库,支持像 SQL 关系数据库和 NoSQL 无模式数据库那样管理数据,目前还在不断更新完善中。

介绍可参考: OnceDB 内存数据库引擎

条件查询

在 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)

  // 定义 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 客户端使用帮助

原文地址: http://onceoa.com/ask/view/k7o21fq9guwe

1373 次点击
所在节点    程序员
1 条回复
longway
2020-03-13 09:10:07 +08:00
支持一下

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/652057

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX