couchdb - проблемы группировки коллекций - PullRequest
0 голосов
/ 10 декабря 2010

У меня возникают проблемы, пытаясь разобраться в том, как собрать коллекцию типов, и сколько раз умение было найдено в этом типе документа.

Существует несколько типов документов, у которых есть списокнавыков.


{
   "skills": "Windows, Network Admin, Linux",
   "type": "Experience"
},
{
   "skills": "Windows, Erlang, Linux",
   "type": "Experience"
},

{
   "skills": "Ruby, Rails, Erlang",
   "type": "Project"
}

Я пытаюсь узнать, сколько раз навык найден в типе документа.

Конечный результат должен выглядеть примерно так:



{
  'type': Experience,
  'skills': [
    {'skill': 'Erlang', 'count': 1},
    {'skill': 'Linux', 'count': 2},
    {'skill': 'Network Admin', 'count': 1},
    {'skill': 'Rails', 'count': 0},
    {'skill': 'Ruby', 'count': 0},
    {'skill': 'Windows', 'count': 2}
  ]
},
{
  'type': Project,
  'skills': [
    {'skill': 'Erlang', 'count': 1},
    {'skill': 'Linux', 'count': 0},
    {'skill': 'Network Admin', 'count': 0},
    {'skill': 'Rails', 'count': 1},
    {'skill': 'Ruby', 'count': 1},
    {'skill': 'Windows', 'count': 0}
  ]
}

Как лучше всего это сделать?

Ответы [ 2 ]

1 голос
/ 11 декабря 2010

Вы должны хранить список навыков в ваших документах как реальный список.

{
   "skills": ["Windows", "Network Admin", Linux"],
   "type": "Experience"
}

Оттуда ваша функция карты становится:

function(doc) {
  for(var skill in doc.skills) {
    emit([doc.type, skill], 1);
  }
}

А функция уменьшения просто суммирует результат, поэтому используйте " _sum ". Вы можете легко выбрать отображение только опыта или проекта с клавишами начала и конца.

0 голосов
/ 03 апреля 2011

Здесь представлены функции map и Reduce (представление с именем skill_split) и функция списка, которая будет производить вывод, близкий к тому, что вы просили, используя URL-адрес, подобный этому http://127.0.0.1:5984/myskills/_design/myskills/_list/transform/skill_split?group=true:

{
   "Experience": {"Erlang":1, "Linux":2, "Network Admin":1, "Windows":2},
   "Project":{"Erlang":1, "Rails":1, "Ruby":1}
}

Я могунастройте код, чтобы сделать вывод именно таким, как вы просили, но функция списка будет немного длиннее.

map :

function(doc) {
  if (doc.type && doc.skills) {
    doc.skills.split(', ').forEach(function(skill) {
      emit([doc.type, skill], 1);
    });
  }
}

уменьшите:

function(keys, values, rereduce) {
  return sum(values)
}

или используйте "reduce": "_sum" для краткости

список (с именем transform):

function(head, req) {
  var results = {};
  var row;
  while (row = getRow()) {
    var skill_map;
    if (results.hasOwnProperty(row.key[0])) {
      skill_map = results[row.key[0]];
    } else {
      skill_map = {};
      results[row.key[0]] = skill_map;
    }

    if (skill_map.hasOwnProperty(row.key[1])) {
      skill_map[row.key[1]] = skill_map[row.key[1]] + row.value;
    } else {
      skill_map[row.key[1]] = row.value;
    }
  }
  send(JSON.stringify(results));
}

Еслиу вас нет доступа к объекту JSON (вы делаете это внутри CouchApp), вам, возможно, придется перепрыгнуть через несколько обручей, чтобы получить к нему доступ.

...