如何在 CouchDB reduce 函数中进行 GROUP BY

How to GROUP BY in a CouchDB reduce function

我试图在使用 PouchDB/CouchDB 时掌握 map/reduce 查询。

我的数据库中有很多文档,但我需要创建一个设计来查询这些文档并为我提供所有唯一的团队名称作为键,然后告诉我

a) how many unique wards are within each team

b) the total number of jobs per team (across all wards)

我的数据结构是:

{
    "_id": "0448071807c0f37f53e06aab54034a42",
    "_rev": "6-13fd78ada9c8833ec36a01af0acd5957",
    "team": "Team A",
    "ward": "Ward A",
    "date": "2017-03-30",
    "person": "Alice",
    "bed": "Bed 001",
    "jobs": [1,2,3,4]
}

{
    "_id": "0448071807c0f37f53e06aab54034a42",
    "_rev": "6-13fd78ada9c8833ec36a01af0acd5957",
    "team": "Team A",
    "ward": "Ward B",
    "date": "2017-03-30",
    "person": "Bob",
    "bed": "Bed 001",
    "jobs": [1,2]
}   

{
    "_id": "0448071807c0f37f53e06aab54034a42",
    "_rev": "6-13fd78ada9c8833ec36a01af0acd5957",
    "team": "Team A",
    "ward": "Ward C",
    "date": "2017-03-30",
    "person": "Charles",
    "bed": "Bed 001",
    "jobs": [9,5]
}   

{
    "_id": "0448071807c0f37f53e06aab54034a42",
    "_rev": "6-13fd78ada9c8833ec36a01af0acd5957",
    "team": "Team B",
    "ward": "Ward 00",
    "date": "2017-03-30",
    "person": "David",
    "bed": "Bed 001",
    "jobs": [1]
}   

我期望的输出是这样的:

A 队 - 3 个独特的病房 - 8 个职位

B 队 - 1个独特病房 - 1 份工作

例如

{
    "key": "Team A",
    "value": {
        "wards": 3,
        "jobs": 8
    }
}

{
    "key": "Team B",
    "value": {
        "wards": 1,
        "jobs": 1
    }
}

我的地图目前是:

{
   "all": {
       "map": "function(doc) { emit(doc.team, doc) }"
   }
}

这是我挣扎的地方。

编辑

我采纳了 CouchDB View equivalent of SUM & GROUP BY 中使用的建议,但这只完成了我的挑战的一半。

如果我使用:

{
   "all": {
       "map": "function(doc) { emit([doc.team, doc.ward], 1) }",
       "reduce": "function(keys, values) { return sum(values); }"
   }
}

然后转到 http://my-ip:5984/wardround_jobs/_design/teams/_view/all?group_level=1 然后我看到独特的团队(好)和出现次数(也很好)但我不确定我如何扩展 reduce 函数以包括工作总数。

首先,您必须发出作业长度(有作业数):

function (doc) {
  emit([doc.team,doc.ward],doc.jobs.length);
}

那么,你需要一个这样的reduce函数:

function (keys, values, rereduce) {
  var stats = {uniq:0,jobs:0};
  if (rereduce) {
    for(var i=0;i<values.length;i++){
     stats.uniq += values[i].uniq;
     stats.jobs += values[i].jobs;
    }
    return stats;
  }
  stats.uniq = values.length;
  stats.jobs = sum(values);
  return stats;
}

对于第一次迭代,我们 return 一个对象 (stats),其中包含 wards perm team (uniq) 的数量和工作数量(我们将每个 team/ward 的工作长度相加)。

然后,对于重新归约,我们只需聚合对象的值。