V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
newghost
V2EX  ›  程序员

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

  •  
  •   newghost ·
    newghost · 2020-03-12 09:18:05 +08:00 · 1374 次点击
    这是一个创建于 1721 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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

    1 条回复    2020-03-13 09:10:07 +08:00
    longway
        1
    longway  
       2020-03-13 09:10:07 +08:00
    支持一下
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3013 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 14:51 · PVG 22:51 · LAX 06:51 · JFK 09:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.