链接之间有什么区别:
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!
最佳答案
我认为第二种情况(带有多个filter
表达式的单个and
)是最有效和最方便的使用方式。
我会考虑以下几点:r.filter
就像documented一样,总是创建新的选择,流或数组,而不管谓词函数的结果传递给r.filter
。
我不确定RethinkDB中的选择如何实现(我相信它们像流一样),但是数组链接可能是分配中间数组的昂贵操作。
将此与Array.prototype.filter
进行比较,它会创建一个新数组作为其结果。
流是惰性的,因此每个元素的计算也是(或不是)惰性的,因此占用的内存较小。
将其与其他语言的迭代器/流和生成器(Java中的Iterator<E>
/Stream<E>
,.NET/C#中的IEnumerator<T>
和yield return
,JavaScript中的迭代器和生成器函数,Python中的yield
, shell 程序命令中的管道|
等进行比较)迭代器/生成器。
无论如何,您都有中间过滤器。
单个表达式可以代替一堆链接的过滤器操作。
请注意,表达式中的r.and
操作具有一个非常重要的功能:这是短路评估操作。
如果AND操作的左侧操作数为false
,则该操作甚至不需要评估右侧表达式即可获得始终为false
的结果。
您不能使用r.filter
做这样的事情。
将此与可以在单个查询中指定一次的SQL WHERE子句进行比较(所有错误的情况都可以由AND
运算符简单地丢弃)。
同样,从务实的角度来看,您可以创建一个工厂方法,该工厂方法可以使用方便的名称并返回参数化的ReQL表达式,由于ReQL表达式是不可变的并且可以安全重用,因此甚至可以将其分配给常量:
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)
ReQL表达式RethinkDB查询实际上是表达式树,比执行JavaScript脚本更容易解析和直接转换为执行计划。
甚至recommends的官方文档也避免使用
r.js
以获得更好的性能。我想这里的代价是JavaScript运行时设置,隔离的脚本执行以及检查脚本超时。
此外,脚本更容易出错,而在编译期间可以或多或少地检查表达式树。
但是,出于完整性考虑,即使RetL是有限的一组操作,
r.js
甚至可能会更强大,因为这些开销。从我的个人经验来看:我必须实现一种基于RethinkDB的权限检查子系统,并且我需要在RethinkDB中进行按位AND操作。
不幸的是,从2.3版本开始,RethinkDB不支持按位操作,因此我不得不使用
r.js
:r.js('(function (user) { return !!(user.permissions & ${permissions}); })')
。RethinkDB的 future 版本将支持bitwise operations,因此
r.getField('permissions').bitAnd(permissions))
应该在将来的某一天更快地运行,并且可以与其他表达式组合以适合单个filter
。关于rethinkdb |嵌套查询与链接查询有什么区别?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49307180/