我刚刚开始搞乱CouchDB。在许多地方,我已经看到它表明CouchDB视图的reduce函数需要是关联的和可交换的(例如,the CouchDB wiki说明这一点)。我确实理解CouchDB可以分阶段进行减少,并通过重新减少来缓存和重用中间结果。我也清楚为什么reduce函数必须是关联的。但是,我不明白交换要求来自何处。
让我试着更清楚一点。假设我有一个map函数,它在我的数据库的所有内容上运行时输出10个值。为简单起见,假设这些值是整数1 - 10(1,2,3,4等)。
假设我有一个函数f(keys, values, rereduce)
,它是关联的,但不是可交换的。让我们说f
忽略键并重新声明参数,并且只对values数组进行操作。因此,我将在其余的解释中省略键并重新减少参数。
据我了解,交换属性需要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]
的结果,它可以使用rereduce == true
调用我的reduce函数,只传递f([1, 2])
并f([3, 4])
计算f([1, 2, 3, 4])
,而无需我的代码处理所有4项。
应用
对于它的价值,我有一个用例,我的地图输出是排列。由于置换函数是关联的,但不是可交换的,我想我可以使用CouchDB减少缓存来真正有效地做一些很酷的事情。而且,在我的测试中,它似乎有效。但是wiki,CouchDB书和其他消息来源说减少必须是可交换的,因此我不应该这样做。
答案 0 :(得分:0)
将此内容发布到CouchDB邮件列表和got an answer。目前看来,减少功能不需要是可交换的。但是,CouchDB计划集成BigCouch,此时数据将在多个服务器之间进行分片。在该环境中,传递给reduce函数的值可以基本上是随机的,因此需要可交换。
如果只有一个分片,非交换函数将继续正常工作,而CouchDB团队并不认为这将始终有效;他们保留将来改变事物的权利,并且只能承诺如果它是可交换的,你的减少将起作用。