【发布时间】:2013-12-16 16:31:58
【问题描述】:
我刚刚开始使用 CouchDB。在很多地方,我看到它声明 CouchDB 视图的 reduce 函数需要同时具有关联性和可交换性(例如,the CouchDB wiki 就是这样说的)。我确实了解 CouchDB 可以分阶段进行 reduce 并通过 re-reduce 缓存和重用中间结果。我也很清楚为什么 reduce 函数必须是关联的。但是,我不明白交换要求的来源。
让我试着说得更清楚一点。假设我有一个 map 函数,它在运行我的数据库的所有内容时输出 10 个值。为简单起见,假设这些值是整数 1 - 10(1、2、3、4 等)。
假设我有一个函数f(keys, values, rereduce),它是关联的,但不是可交换的。假设f 忽略键并重新减少参数,并且仅对值数组进行操作。因此,我将在其余的解释中省略键并重新减少论点。
据我了解,交换属性需要f([1, 2]) == f([2, 1]),但我认为 CouchDB 永远不会这样做。我确实理解它可能会将之前在地图输出子集上的 f 计算结果传递给我,但我相信它总是会按顺序将它们传递给我。例如,我可能会被调用,使用rereduce == true,如f([f([1, 2, 3]), f([4, 5, 6])]),但我认为我的reduce 函数不会像f([f([4, 5, 6]), f([1, 2, 3])]) 或以任何其他类似的方式调用,其中数组参数不是“有序的” ”。如果那是正确的,那么我确实理解为什么我的 reduce 函数需要是可交换的。
补充说明:
整个问题都在上面,但如果它有助于某人理解我的困惑,这里是我对关联属性要求的理解。
在我看来,f 具有关联性意味着:
f([1, 2, 3]) == f([f([1, 2]), 3]) == f([1, f([2, 3])]) == f([f([1]), f([2, 3])]) == f([f([1, 2]), f([3])])
第一个 3 是二元运算符的标准数学关联定义。由于我们正在使用数组和非二元运算符,最后两个是一个轻微的概括。因此,例如,如果 CouchDB 缓存了减少 [1, 2] 和减少 [3, 4] 的结果,它可以调用我的 reduce 函数,使用 rereduce == true,只传递 f([1, 2]) 和 f([3, 4]) 来计算 @987654336 @,不需要我的代码处理所有 4 个项目。
应用程序
对于它的价值,我有一个用例,其中我的地图输出是排列。由于置换函数是关联的,但不是可交换的,我想我可以使用 CouchDB 减少缓存来真正有效地做一些很酷的事情。而且,在我的测试中,它似乎有效。但是 wiki、CouchDB 书和其他来源说 reduce 必须是可交换的,因此我不应该这样做。
【问题讨论】: