CouchDB вид уменьшить один до c на клавишу - PullRequest
0 голосов
/ 16 февраля 2020

Я пытаюсь решить что-то вроде довольно простой проблемы с представлением couchDb, но я даже не приближаюсь к цели с моим набором результатов.

Вместо того, чтобы обновлять документы, я каждый раз создаю новый документ в качестве стратегии управления версиями и связываю эти документы вместе с полем контроля версий под названием ver. Самый первый документ в цепочке версий увидит поле ver и поле _id, имеющие одинаковое значение. Все последующие документы в цепочке будут иметь то же поле ver, что и предыдущие документы в цепочке, но будут иметь уникальное поле _id. Эти документы также имеют поле createdTime, которое позволяет мне узнать, какой документ является самым последним.

Вот мои документы:

{
  "_id": "abcd-1234-efgh-9876",
  "ver": "abcd-1234-efgh-9876",
  "createdTime": "2020-01-12 01:15:00 PM -0600",
  ...
},
{
  "_id": "uopa-3849-pmdi-1935",
  "ver": "abcd-1234-efgh-9876",
  "createdTime": "2020-02-16 02:39:00 PM -0600",
  ...
}

Вот моя функция карты:

function (doc) {
  emit(doc.ver, doc);
}

Вот моя функция сокращения:

function(keys, values, rereduce) {
    var latestVersions = {};

    for (var i = 0; i < keys.length; i++) {
      var found = latestVersions[keys[i][0]];
      if (!found || found.createdTime < values[i].createdTime) {
        latestVersions[keys[i][0]] = values[i];
      } 
    }

    return latestVersions;
}

И, наконец, вот мой желаемый вывод из представления (просто do c, который я хочу):

{
  "_id": "uopa-3849-pmdi-1935",
  "ver": "abcd-1234-efgh-9876",
  "createdTime": "2020-02-16 02:39:00 PM -0600",
  ...
}

Что я здесь скучаю? Функция Reduce возвращает обе записи, а это не то, что мне нужно. Это то, что я пытаюсь достичь возможно или есть лучший способ go об этом?

Обновление

Я смог заставить это работать, когда один ключ используется для доступа к представлению, что является одним из моих вариантов использования.

function (keys, values, rereduce) {
  var toReturn = values[0];
    for (var i = 1; i < values.length; i++) {
      if (values[i].createdTime > toReturn.createdTime) {
        toReturn = values[i];
      }
    }

    return toReturn;
}

Однако у меня есть другой вариант использования, который будет возвращать все данные в представлении. Желаемый результат там такой же, как и выше, но функция, которую я использую для одиночных клавиш, будет возвращать только один результат. Как отфильтровать несколько значений с помощью общего ключа, чтобы 1 «общий» ключ: n значений -> 1 ключ: 1 значение.

1 Ответ

0 голосов
/ 21 февраля 2020

Я наконец смог решить эту проблему, когда наткнулся на эту статью на диване . Это было намного более ясно, чем некоторые другие dry компьютерные документы.

Я до сих пор не понимаю, почему некоторые элементы сгруппированы по методу уменьшения, а другие нет. Например, сокращение было вызвано 5 раз для 6 элементов, которые имели одинаковый ключ; только один из ключей фактически сгруппировал что-либо - массив из двух документов. Вероятно, это как-то связано с теми документами B-дерева по информатике dry, о которых я говорил.

В любом случае, я смог определить, что все, что мне нужно было сделать, - это сгруппировать значения по полю ver в обоих сценариях ios (единственное отличие состоит в том, что для восстановления используется двумерный массив). Вот как выглядит моя функция сокращения:

function (keys, values, rereduce) {

  var toValues = function(myMap) {
    return Object.keys(myMap).map(function(key) {
      return myMap[key];
    });
  }

  if (rereduce) {
    // values should look like [[{...}, {...}], [{...}]]
    var outputMap = {};

    for (var i = 0; i < values.length; i++) {
      for (var j = 0; j < values[i].length; j++) {
        var currentEl = values[i][j];
        var found = outputMap[currentEl.ver];

        if ((found && found.createdDate < currentEl.createdDate) || !found) {
            outputMap[currentEl.ver] = currentEl;
        }
      }
    }

    return toValues(outputMap);
  } else {
    var outputMap = {};

    for (var i = 0; i < values.length; i++) {
      var found = outputMap[values[i].ver];

      if ((found && found.createdDate < values[i].createdDate) || !found) {
          outputMap[values[i].ver] = values[i];
      }

    }

    return toValues(outputMap);
  }
}
...