2011-11-11 1 views
0

다음 bash는 스크립트를 사용하여 DB를 만들기 :거의 동일한 뷰에서 부동 소수점 정밀도가 다릅니 까?

#! /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 내가 얻을 http://127.0.0.1:5984/sales/_design/logic/_view/total_purchases

을 GET :

을 { "행": [{ "키": null, "값": 2557.65}]}

하지만 total_purchases의 난 (doc.LastName, doc.TotalSpent)을 방출하는 발광의 최초의 파라미터를 변경하는 경우, 그때 얻을 것이다

{ "행" [{ "키"널 (null), "값"2557.6499999999996}]} 왜 그렇게

?

답변

1

답변의 차이는보기 기능을 변경했기 때문입니다. 방출 할 첫 번째 매개 변수는 뷰 색인 작성 방법을 결정합니다. 첫 번째 경우, 생성 된 모든 값은 'null'키 아래에 저장됩니다. 두 번째 예제를 사용하여 이제는 고객의 성 (last name)과 같은 다른 키를 중심으로 색인을 분산 시켰습니다.

따라서 couchdb의 내부 btree는보기간에 서로 다릅니다. 그렇다면 왜 다른 결과를 얻을 것입니까?

CouchDB는 증분 맵/축소를 사용합니다. 당신은 여기에 대해 읽을 수 있습니다 : http://damienkatz.net/2008/02/incremental_map.html

를 해당 게시물에서 데미안이 점한다 : (가) 함수가 referentially 투명해야뿐만 아니라 요구 사항이 감소

증분지도/수 감소하게하기를, 배열 값 입력에 대한 교환 가능하고 연관성이 있어야합니다. 즉, 자신의 출력을 줄이고 다음과 같은 대답을 얻을 수 있어야합니다.

f (키, 값) == f (키, 키, 값)])

감소 함수의 요구 사항은 CouchDB가 btree 인덱스의 내부 노드에 직접 중간 감소를 저장하고 뷰 인덱스 업데이트 및 검색에 로그 비용이 들게합니다. 또한 인덱스를 시스템에 분산시키고 로그 비용으로 쿼리 시간을 단축 할 수 있습니다.

증분 디자인을 사용하면 map/reduce를 사용하여 전체 맵/축소 작업이 완료 될 때까지 대기하거나 가끔씩 업데이트되는 인덱스가있을 때까지 기다릴 필요없이 실시간으로 거대한 파티션 클러스터를 쿼리 할 수 ​​있습니다. 단점은 연관 및 교환 방식으로 축소 기능을 작성하는 것이 더 어려울 수 있다는 것입니다.

따라서 첫 번째보기에서는 모두 동일한 키 아래에 있으므로 저장된 중간 축소는 없습니다. 두 번째보기에서는 임시 합계가 저장됩니다.아마도 이러한 중간 합계에 부동 소수점 숫자가 저장되는 방식의 차이를 볼 수 있습니다. 참조 : Is floating point math broken?

두 가지 권장 사항으로 문제를 해결할 수 있습니다. 첫 번째는 Erlang 버전의 reduce 함수에 'built-in'호출을 사용하는 것입니다. 여기를 참조하십시오 :

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

을 호출이 약간 다르다 "감소": "_sum"

두 번째 여기와 같이, 당신은 변환은 정수로 플로트를 방출 할 수 : Is floating point math broken?

희망이 도움이됩니다.

+0

알다시피, 고객 수를 7로 늘리면 키 필드가 null 인 경우에도 출력 결과가 잘못 표시됩니다. 그러나 어쨌든 감사와 +1. – Yola

+0

방금 ​​더 추가하나요? 그것은 여전히 ​​'증분'일 수있었습니다. erlang _sum 함수를 사용해 보셨습니까? –

관련 문제