链接之间有什么区别:
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!
答案 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.js
:r.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 会默默地失败。