rethinkdb |嵌套vs链式查询,有什么区别?

时间:2018-03-15 18:53:04

标签: rethinkdb rethinkdb-javascript

链接之间有什么区别:

r.db('catbox').table("bw_mobile").filter(
    r.row("value")("appVersion")("major").le(2)
).filter(
  r.row("value")("appVersion")("minor").le(2)
).filter(
  r.row("value")("appVersion")("patch").le(10)
)

嵌套:

r.db('catbox').table("bw_mobile").filter(
      r.row("value")("appVersion")("major").le(2).and(
        r.row("value")("appVersion")("minor").le(2).and(
          r.row("value")("appVersion")("patch").le(10)
        )
      )
)

或lambda函数

r.db('catbox').table("bw_mobile").filter(
  r.js("(function (session) { 
        return session.value.appVersion.major < 0 
            || ( session.value.appVersion.major == 0 && session.value.appVersion.minor < 0 )
            || ( session.value.appVersion.major == 0 && session.value.appVersion.minor == 0 && session.value.appVersion.patch < 71 )
        ; 
    })")
)

TY!

2 个答案:

答案 0 :(得分:2)

我认为第二种情况(单个filter具有多个and表达式)是最有效和最方便使用的。 我会考虑以下想法:

r.filter,因为它是documented始终创建新的选择,流或数组,无论传递给{{的谓词函数的结果如何1}}。 我不确定在RethinkDB中如何实现选择(我相信它们是流式的),但是数组链接可能是分配中间数组的昂贵操作。 将此与r.filter进行比较,后者会创建一个新数组作为结果。 流是懒惰的,因此每个元素也可以懒惰地计算(或不计算),因此可以缩小内存占用量。 将其与其他语言中的迭代器/流和生成器进行比较(Java中为Array.prototype.filter / Iterator<E>,.NET / C#中为Stream<E>IEnumerator<T>,JavaScript中为迭代器和生成器函数, Python中的yield return,shell命令中的管道yield等),您可以在其中组合迭代器/生成器。 无论如何,你都有中间过滤器。

单个表达式可以替换一堆链接过滤器操作。 请注意,表达式中的|操作有一个非常重要的特性:这是一个短路评估操作。 如果AND操作的左侧操作数为r.and,则操作甚至不需要评估右侧表达式以获得始终为false的结果。 你不能用false来做这件事。 将此与每个查询可以指定一次的SQL WHERE子句进行比较(r.filter运算符可以简单地丢弃所有错误情况)。 此外,从实用的角度来看,您可以创建一个工厂方法,该方法可以具有方便的名称并返回参数化的ReQL表达式,甚至可以将其分配给常量,因为ReQL表达式是不可变的并且可以安全地重复使用:

AND

ReQL表达式RethinkDB查询实际上是表达式树,它比执行JavaScript脚本更容易解析并直接转换为执行计划。 甚至recommends的官方文档也避免使用const maxVersionIs = (major, minor, patch) => r.row("value")("appVersion")("major").le(major) .and(r.row("value")("appVersion")("minor").le(minor)) .and(r.row("value")("appVersion")("patch").le(patch)); const versionPriorToMilestone = maxVersionIs(2, 2, 10); ... .filter(maxVersionIs(major, minor, patch)) ... .filter(versionPriorToMilestone) 来提高性能。 我想这里的成本是JavaScript运行时设置,隔离脚本执行和检查脚本超时。 此外,脚本更容易出错,而在编译期间可以或多或少地检查表达式树。 但是,为了完整起见,即使有这些成本,r.js也可能更强大,因为ReQL是一组有限的操作。 根据我的个人经验:我必须实现一种基于RethinkDB的权限检查子系统,我需要在RethinkDB中进行按位AND操作。 不幸的是,从2.3开始的RethinkDB不支持按位操作,所以我不得不使用r.jsr.js。 RethinkDB的未来版本将支持bitwise operations,因此r.js('(function (user) { return !!(user.permissions & ${permissions}); })')将来某一天应该能够更快地与其他表达式结合使用,以适应单个r.getField('permissions').bitAnd(permissions))

答案 1 :(得分:0)

因为我昨晚遇到了类似的问题,而且这里没有很多 RethinkDB 内容,我将分享我的解决方案。

export interface LooseObjectInterface {
  [key: string]: any;
};

const tldQuery: LooseObjectInterface = await r.table(tldDatabase)
  .orderBy({ index: r.asc("name") }) // alphabetical sort
  .filter((row: any) => {
    return row("collection")
      .contains(suppliedCollection[0])
      .or(row("collection").contains(suppliedCollection[1]))
      .or(row("collection").contains(suppliedCollection[2]))
      .or(row("collection").contains(suppliedCollection[3]))
      // ^ these extra "or"s silently fail, huzzah!
  })
  .pluck("name") // we just want the names
  .run(databaseConnection);

在我的代码中,suppliedCollection 是一个字符串数组。我表中的每一项都可以在 suppliedCollection 中包含任意数量的字符串,从 1 到 4。

基于一个项目集合中的这些字符串,我想找到包含这些相同字符串的其他项目。

幸运的是,如果 suppliedCollection[n]undefined,RethinkDB 会默默地失败。