2011-11-11 65 views
0

與未來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) }" 
     } 
    } 
} 

當我打電話 捲曲-X GET http://127.0.0.1:5984/sales/_design/logic/_view/total_purchases

我得到:

{ 「rows」:[{「key」:null,「value」:2557.65}]}

,但如果我在total_purchases改變發射到發射(doc.LastName,doc.TotalSpent)第一參數,然後我將獲得:

{ 「行」: [{ 「鑰匙」:空, 「值」:2557.6499999999996}]}

爲什麼會這樣?

回答

1

你的答案之間的區別是由於你改變了你的視圖功能。要發射的第一個參數決定如何構建視圖索引。在第一種情況下,所有發射的值將被存儲在'空'鍵下。通過第二個示例,您現在可以將索引分散在不同的鍵上,即客戶的姓氏。

因此,couchdb中的內部樹會在視圖之間不同。那麼爲什麼你會得到不同的結果呢?

CouchDB使用增量映射/減少。你可以在這裏讀到: http://damienkatz.net/2008/02/incremental_map.html

從該職位達明使點:

進行增量的Map/Reduce可能,減少函數,不僅必須是引用透明的要求,但它也必須是交換和相關的數組值輸入,以便能夠減少它自己的輸出並得到相同的答案,如下所示:

f(Key,Values)== f(Key,[f(鍵,值)])

對reduce函數的這種要求允許CouchDB將中間減少直接存儲到btree索引的內部節點中,並且視圖索引更新和檢索將具有對數成本。它還允許索引分佈在不同的機器上,並在查詢時以對數成本降低。

增量設計使得使用map/reduce實時查詢巨大的分區集羣成爲可能,而不必等待整個map/reduce作業完成或有過時的偶爾更新的索引。缺點是可能難以以關聯和交換的方式編寫Reduce函數。

因此,我假定發生的事情是,在第一個視圖中,因爲它們都在同一個鍵下,所以沒有存儲的中間縮減。而在第二個視圖中,臨時總和正在被存儲。然後您可能會看到浮點數存儲在這些中間值中的差異。看到這裏: Is floating point math broken?

兩個建議可能會幫助你解決這個問題。首先是對Erlang版本的reduce函數使用「內置」調用。在這裏看到:

http://wiki.apache.org/couchdb/Built-In_Reduce_Functions

呼叫略有不同: 「減少」: 「_sum」

其次,你可以轉換髮出浮動爲一個整數,如下所示: Is floating point math broken?

希望這有助於。

+0

你知道,當我把客戶數量增加到7時,即使以null爲關鍵字段,其輸出也會出現錯誤的精度。但無論如何感謝和+1。 – Yola

+0

你剛加了一個嗎?它可能仍然是「增量」的。你有沒有嘗試erlang _sum函數? –