Mapreduce 为什么CouchDB Reduce函数必须是可交换的?

Mapreduce 为什么CouchDB Reduce函数必须是可交换的?,mapreduce,couchdb,Mapreduce,Couchdb,我刚开始和CouchDB鬼混。在许多地方,我看到它指出CouchDB视图的reduce函数需要是关联的和可交换的(例如,这样说)。我知道CouchDB可以分阶段进行reduce,并通过reduce缓存和重用中间结果。我也很清楚为什么reduce函数必须是关联的。然而,我不明白交换性要求从何而来 让我再清楚一点。假设我有一个map函数,在运行数据库的所有内容时输出10个值。为了简单起见,假设这些值是整数1-10(1、2、3、4等) 假设我有一个函数,f(键、值、重导出),它是关联的,但不是可交换的

我刚开始和CouchDB鬼混。在许多地方,我看到它指出CouchDB视图的reduce函数需要是关联的和可交换的(例如,这样说)。我知道CouchDB可以分阶段进行reduce,并通过reduce缓存和重用中间结果。我也很清楚为什么reduce函数必须是关联的。然而,我不明白交换性要求从何而来

让我再清楚一点。假设我有一个map函数,在运行数据库的所有内容时输出10个值。为了简单起见,假设这些值是整数1-10(1、2、3、4等)

假设我有一个函数,
f(键、值、重导出)
,它是关联的,但不是可交换的。假设
f
忽略键并重新导出参数,只对值数组进行操作。因此,我将在其余的解释中省略键并重新推导参数

据我所知,交换属性需要
f([1,2])==f([2,1])
,但我认为CouchDB永远不会这样做。我确实理解,它可能会将先前对map输出子集进行的
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个是二进制运算符的标准数学关联定义。由于我们使用的是数组和非二进制运算符,最后2个是一个轻微的推广。因此,例如,如果CouchDB缓存了reduce的结果
[1,2]
和reduce的结果
[3,4]
,它可以调用我的reduce函数,使用
rereduce==true
,只传递
f([1,2])
f([3,4])
来计算
f([1,2,3,4])
,不需要我的代码来处理所有4项

应用程序


值得一提的是,我有一个用例,其中我的映射输出是排列。因为置换函数是关联的,但不是交换的,所以我想我可以使用CouchDB reduce缓存来非常有效地完成一些很酷的事情。而且,在我的测试中,它似乎起了作用。但是wiki、CouchDB书籍和其他来源说reduce必须是可交换的,因此我不应该这样做。

将此发布到CouchDB邮件列表中,并进行了修改。目前,reduce函数似乎不需要是可交换的。然而,CouchDB计划集成BigCoach,届时数据将在多台服务器上进行分片。在这种环境中,传递给reduce函数的值基本上是随机的,因此需要交换的

虽然如果只有一个碎片,非交换函数将继续正常工作,但CouchDB团队并没有承诺这将始终有效;他们保留在将来改变事情的权利,并且只能承诺如果你的reduce是可交换的,那么它将起作用