2013-04-28 14 views
5

하여 SQL 그룹과 유사한 줄CouchDB를 -지도 CouchDB를 저장 샘플 문서를 다음 고려

{ 
"_id":...., 
"rev":...., 
"type":"orders", 
"Period":"2013-01", 
"Region":"East", 
"Category":"Stationary", 
"Product":"Pen", 
"Rate":1, 
"Qty":10, 
"Amount":10 
} 

{ 
"_id":...., 
"rev":...., 
"type":"orders", 
"Period":"2013-02", 
"Region":"South", 
"Category":"Food", 
"Product":"Biscuit", 
"Rate":7, 
"Qty":5, 
"Amount":35 
} 

SQL 쿼리 다음과 같은 고려

SELECT Period, Region,Category, Product, Min(Rate),Max(Rate),Count(Rate), Sum(Qty),Sum(Amount) 
FROM Sales 
GROUP BY Period,Region,Category, Product; 

가능/맵을 생성에 CouchDB를 환산 뷰를 줄이는 것입니다 위의 SQL 쿼리와 같은 출력을 생성

[ 
    { 
     "Period":"2013-01", 
     "Region":"East", 
     "Category":"Stationary", 
     "Product":"Pen", 
     "MinRate":1, 
     "MaxRate":2, 
     "OrdersCount":20, 
     "TotQty":1000, 
     "Amount":1750 
    }, 
    { 
    ... 
    } 

] 
+0

아직 시도해 보셨나요? 간단한보기가 잘 작동합니다. 몇 가지 샘플 문서는 누군가가 당신에게보다 구체적이고 상세한 대답을 줄 수 있도록 도와줍니다. –

+0

@DominicBarnes 몇 가지 샘플 문서를 제공했습니다. –

답변

3

앞에서 볼 때, 나는 @ benedolph의 대답이 베스트 프랙티스와 최상의 경우 시나리오라고 믿습니다. 각 reduce는 코드를 최대한 단순하게 유지하기 위해 1 스칼라 값을 반환하는 것이 이상적입니다.

그러나 질문에 설명 된 전체 결과 집합을 검색하려면 여러 쿼리를 실행해야합니다. 쿼리를 병렬로 실행할 수있는 옵션이 없거나 쿼리 수를 줄이는 것이 중요하다면 모든 쿼리를 한꺼번에 수행 할 수 있습니다.

지도 기능은 아주 간단 남아 :

function (key, values, rereduce) { 
    // helper function to sum all the values of a specified field in an array of objects 
    function sumField(arr, field) { 
     return arr.reduce(function (prev, cur) { 
      return prev + cur[field]; 
     }, 0); 
    } 

    // helper function to create an array of just a single property from an array of objects 
    // (this function came from underscore.js, at least it's name and concept) 
    function pluck(arr, field) { 
     return arr.map(function (item) { 
      return item[field]; 
     }); 
    } 

    // rereduce made this more challenging, and I could not thoroughly test this right now 
    // see the CouchDB wiki for more information 
    if (rereduce) { 
     // a rereduce handles transitionary values 
     // (so the "values" below are the results of previous reduce functions, not the map function) 
     return { 
      OrdersCount: sumField(values, "OrdersCount"), 
      MinRate: Math.min.apply(Math, pluck(values, "MinRate")), 
      MaxRate: Math.max.apply(Math, pluck(values, "MaxRate")), 
      TotQty: sumField(values, "TotQty"), 
      Amount: sumField(values, "Amount") 
     }; 
    } else { 
     var rates = pluck(values, "Rate"); 

     // This takes a group of documents and gives you the stats you were asking for 
     return { 
      OrdersCount: values.length, 
      MinRate: Math.min.apply(Math, rates), 
      MaxRate: Math.max.apply(Math, rates), 
      TotQty: sumField(values, "Qty"), 
      Amount: sumField(values, "Amount") 
     }; 
    } 
} 

내가에서이 코드의 지점을 "rereduce"를 테스트 할 수 없습니다 : 긴 얻는 곳

function (doc) { 
    emit([ doc.Period, doc.Region, doc.Category, doc.Product ], doc); 
} 

이 기능은 감소 모두, 당신은 그것을 끝까지해야 할 것입니다. (하지만이 작업은 가능합니다.) 감소 대 재 감소에 대한 정보는 the wiki을 참조하십시오.

내가 맨 위에 추가 한 도우미 기능 덕분에 전반적으로 코드가 훨씬 짧아지고 읽기가 쉬워졌으며, 이는 내 경험에 따라 크게 영향을 받았습니다. Underscore.js. 그러나 reduce 함수에는 CommonJS 모듈을 포함 할 수 없으므로 수동으로 작성해야합니다.

다시 말해, 각 집계 된 필드에 자체 map/reduce 인덱스를 가져 오는 것이 가장 좋은 시나리오이지만,이 옵션이 선택 사항이 아닌 경우 위의 코드는 질문에서 여기서 설명한 내용을 가져와야합니다 .

+0

시간과 자세한 답변을 보내 주셔서 감사합니다. 나는 당신의 해결책을 따를 것입니다. –

2

나는 아주 간단한 "select"절에서 집계 할 변수 당 하나의보기가 필요한 솔루션입니다. 단일 뷰에 모든 변수을 집계하는 것이 가능하지만 reduce 함수는 훨씬 더 복잡합니다.

설계 문서는 다음과 같습니다

{ 
    "_id": "_design/ddoc", 
    "_rev": "...", 
    "language": "javascript", 
    "views": { 
     "rates": { 
      "map": "function(doc) {\n emit([doc.Period, doc.Region, doc.Category, doc.Product], doc.Rate);\n}", 
      "reduce": "_stats" 
     }, 
     "qty": { 
      "map": "function(doc) {\n emit([doc.Period, doc.Region, doc.Category, doc.Product], doc.Qty);\n}", 
      "reduce": "_stats" 
     } 
    } 
} 

를 이제, 당신이 "속도"변수에 대한 통계를 얻을 수 <couchdb>/<database>/_design/ddoc/_view/rates?group_level=4을 조회 할 수 있습니다. 결과는 다음과 같아야합니다.

{"rows":[ 
{"key":["2013-01","East","Stationary","Pen"],"value":{"sum":4,"count":3,"min":1,"max":2,"sumsqr":6}}, 
{"key":["2013-01","North","Stationary","Pen"],"value":{"sum":1,"count":1,"min":1,"max":1,"sumsqr":1}}, 
{"key":["2013-01","South","Stationary","Pen"],"value":{"sum":0.5,"count":1,"min":0.5,"max":0.5,"sumsqr":0.25}}, 
{"key":["2013-02","South","Food","Biscuit"],"value":{"sum":7,"count":1,"min":7,"max":7,"sumsqr":49}} 
]} 

"Qty"변수의 경우 쿼리는 <couchdb>/<database>/_design/ddoc/_view/qty?group_level=4입니다.

group_level 속성을 사용하면 집계를 수행 할 수준을 제어 할 수 있습니다. 예를 들어, group_level=2으로 쿼리하면 "기간"및 "지역"까지 집계됩니다.

+0

해결책 주셔서 감사합니다. 이것은 단일 변수를 집계 할 때 유용 할 것입니다. –