Couchdb 在几乎相同的视图中浮点精度不同?

Couchdb 在几乎相同的视图中浮点精度不同?,couchdb,floating-accuracy,Couchdb,Floating Accuracy,使用下一个bash脚本创建数据库: #! /bin/bash curl -X PUT http://127.0.0.1:5984/sales IFS=$';' vals=`cat sales_upload.json` for i in $vals do curl -X POST http://127.0.0.1:5984/sales -H "Content-Type: application/json" -d $i done unset IFS 和资源文件: { "Type"

使用下一个bash脚本创建数据库:

#! /bin/bash
curl -X PUT http://127.0.0.1:5984/sales
IFS=$';'
vals=`cat sales_upload.json`
for i in $vals 
do
    curl -X POST http://127.0.0.1:5984/sales -H "Content-Type: application/json" -d $i
done
unset IFS
和资源文件:

{
    "Type" : "customer",
    "LastName" : "Welsh", 
    "FirstName" : "Jim",
    "Address" : "340 West 50th Street, New York, NY",
    "TotalSpent" : 734.34
};
{
    "Type" : "customer",
    "LastName" : "Zuch", 
    "FirstName" : "Bo",
    "Address" : "116 10th Avenue, New York, NY",
    "TotalSpent" : 1102.47
};
{
    "Type" : "customer",
    "LastName" : "Libby", 
    "FirstName" : "Joe",
    "Address" : "611 Fifth Avenue, New York, NY",
    "TotalSpent" : 290.01
};
{
    "Type" : "customer",
    "LastName" : "Grant", 
    "FirstName" : "Sue",
    "Address" : "7 West 55th Street, Manhattan, NY",
    "TotalSpent" : 430.83
};
{
    "Type" : "salesman",
    "LastName" : "Green", 
    "FirstName" : "Gwen",
    "Level" : 1
};
{
    "_id" : "_design/logic",
    "language" : "javascript",
    "views" :
    {
        "customers": {
            "map" : "function(doc) { if (doc.Type == 'customer')  emit(null, {LastName: doc.LastName, FirstName: doc.FirstName, Address: doc.Address}) }"
        },
        "total_purchases": {
            "map" : "function(doc) { if (doc.Type == 'customer')  emit(null, doc.TotalSpent) }",
            "reduce" : "function(keys, values) { return sum(values) }"
        }
    }
}
我打电话的时候 curl-xget

我得到:

{“行”:[{“键”:空,“值”:2557.65}]}

但是,如果我在total_purchases中将emit的第一个参数更改为emit(doc.LastName,doc.totalspend),那么我将得到:

{“行”:[{“键”:空,“值”:2557.64999996}]}


为什么会这样?

答案之间的差异是因为您更改了查看功能。要发出的第一个参数确定如何构建视图索引。在第一种情况下,所有发出的值都将存储在“null”键下。在第二个示例中,您现在将索引分布在不同的键上,即客户的姓氏

因此,couchdb中的内部btree在视图之间是不同的。那么,为什么在求和时会得到不同的结果呢

CouchDB使用增量映射/减少。你可以在这里阅读:

从这篇文章中,达米恩提出了一个观点:

为了使增量映射/约简成为可能,Reduce函数要求它不仅必须是引用透明的,而且对于数组值输入也必须是可交换的和关联的,以便能够对自己的输出进行约简并得到相同的答案,如下所示:

f(键,值)=f(键,[f(键,值)])

reduce函数的这一要求允许CouchDB将中间的reduce直接存储到btree索引的内部节点中,并且视图索引的更新和检索将具有对数成本。它还允许索引分布在机器上,并在查询时以对数成本减少索引

增量设计使得使用map/reduce实时查询巨大的分区集群成为可能,而不必等待整个map/reduce作业完成,也不必使用过时的、偶尔更新的索引,。缺点是,以关联和交换的方式编写Reduce函数可能比较困难

因此,我假设在第一个视图中,由于它们都在同一个键下,因此没有存储中间归约。而在第二个视图中,存储的是临时金额。然后,您可能会看到浮点数存储在这些中间和中的方式有所不同。请看这里:

有两条建议可以帮助您解决这个问题。首先是对reduce函数的Erlang版本使用“内置”调用。请看这里:

调用略有不同:“reduce”:“u sum”

其次,可以将浮点值转换为整数,如下所示:


希望这能有所帮助。

您知道,当我将客户数量增加到7时,即使使用null作为键字段,其输出精度也会出错。但不管怎样,谢谢你,还有+1。你刚才又加了一个吗?它可能仍然是“增量的”。你试过erlang_sum函数吗?