Подтвердить что ты не робот

Сортировка представлений CouchDB по значению

Я тестирую CouchDB, чтобы узнать, как он может обрабатывать некоторые результаты поиска. То, что я хотел бы сделать, - это создать представление, в котором я могу создать верхние запросы из результатов. На данный момент у меня есть что-то вроде этого:

Пример части документа

{
  "query": "+dangerous +dogs",
  "hits": "123"
}

Функция карты (Не совсем то, что мне нужно/нужно, но это достаточно хорошо для тестирования)

function(doc) {
  if (doc.query) {
    var split = doc.query.split(" ");
    for (var i in split) {
      emit(split[i], 1);
    }
  }
}

Уменьшить функцию

function (key, values, rereduce) {
  return sum(values);
}

Теперь это даст мне результаты в формате, где термин запроса - это ключ и счетчик для этого термина справа, что отлично. Но я бы хотел, чтобы это было заказано по значению, а не по ключу. Из его звуков это еще не возможно с CouchDB.

У кого-нибудь есть идеи о том, как я могу получить представление, где у меня есть упорядоченная версия терминов запроса и связанные с ними подсчеты? Я очень новичок в CouchDB, и я просто не могу придумать, как я буду писать необходимые функции.

4b9b3361

Ответ 1

Правда, нет мертвого ответа. Однако есть несколько шаблонов.

  • http://wiki.apache.org/couchdb/View_Snippets#Retrieve_the_top_N_tags. Мне лично это не нравится, потому что они признают, что это хрупкое решение, и код не выглядит расслабляющим.

  • Ответ Avi, который должен сортировать память в вашем приложении.

  • couchdb-lucene, который кажется, что все в конечном итоге нуждаются в помощи!

  • Мне нравится то, что Крис сказал в цитате Ави. Расслабьтесь. В CouchDB базы данных легки и превосходны, давая вам уникальную перспективу ваших данных. В эти дни шум связан с фильтрованной репликацией, которая заключается в том, чтобы вырезать подмножества ваших данных для размещения отдельной БД.

    В любом случае, основы просты. Вы берете .rows из вывода представления и вставляете его в отдельный БД, который просто испускает ключ на счет. Дополнительный трюк состоит в том, чтобы написать очень простую функцию _list. Списки "отображают" вывод сырого дивана в разные форматы. Функция _list должна выводить

    { "docs":
        [ {..view row1...},
          {..view row2...},
          {..etc...}
        ]
    }
    

    Что это будет делать, так это форматировать вывод представления точно так, как это требует API _bulk_docs. Теперь вы можете прокручивать завиток прямо в другой завиток:

    curl host:5984/db/_design/myapp/_list/bulkdocs_formatter/query_popularity \
     | curl -X POST host:5984/popularity_sorter/_design/myapp/_view/by_count
    
  • Фактически, если ваша функция списка может обрабатывать все документы, вы можете просто отсортировать их самостоятельно и вернуть их клиенту, отсортированным.

Ответ 2

Этот появился в списке рассылки пользователей CouchDB, а Крис Андерсон, один из основных разработчиков, написал:

Это общий запрос, но не поддерживается непосредственно CouchDB views - для этого вам нужно скопировать запрос группового сокращения на другую базу данных и создать представление для сортировки по значению.

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

Мне тоже нужно было сделать это недавно, и я закончил это с помощью своего уровня приложения. Это легко сделать в JavaScript:

db.view('mydesigndoc', 'myview', {'group':true}, function(err, data) {

    if (err) throw new Error(JSON.stringify(err));

    data.rows.sort(function(a, b) {
        return a.value - b.value;
    });

    data.rows.reverse(); // optional, depending on your needs

    // do something with the data…
});

Этот пример выполняется в Node.js и использует node-couchdb, но его можно легко адаптировать для работы в браузере или в другой среде JavaScript. И, конечно, концепция переносима на любой язык/среду программирования.

НТН!

Ответ 3

Я не уверен в том, что у вас есть ваш возвращенный результат, но я уверен, что это должно сделать трюк:

emit([doc.hits, split[i]], 1);

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

Ответ 4

На основе ответа Avi я придумал эту функцию списка Couchdb, которая работала для моих нужд, что является просто отчетом самых популярных событий (key = event name, value = attendees).

ddoc.lists.eventPopularity = function(req, res) {
  start({ headers : { "Content-type" : "text/plain" } });
  var data = []
  while(row = getRow()) {
    data.push(row);
  }
  data.sort(function(a, b){
    return a.value - b.value;
  }).reverse();
  for(i in data) {
    send(data[i].value + ': ' + data[i].key + "\n");
  }
}

Для справки, здесь соответствующая функция просмотра:

ddoc.views.eventPopularity = {
  map : function(doc) {
    if(doc.type == 'user') {
      for(i in doc.events) {
        emit(doc.events[i].event_name, 1);
      }
    }
  },
  reduce : '_count'
}

И вывод функции списка (snipped):

165: Design-Driven Innovation: How Designers Facilitate the Dialog
165: Are Your Customers a Crowd or a Community?
164: Social Media Mythbusters
163: Don't Be Afraid Of Creativity! Anything Can Happen
159: Do Agencies Need to Think Like Software Companies?
158: Customer Experience: Future Trends & Insights
156: The Accidental Writer: Great Web Copy for Everyone
155: Why Everything is Amazing But Nobody is Happy

Ответ 5

Это старый вопрос, но я чувствую, что он по-прежнему заслуживает достойного ответа (я потратил не менее 20 минут на поиск правильного ответа...)

Я не одобряю другие предложения в ответах здесь и считаю, что они неудовлетворительны. Особенно мне не нравится предложение сортировать строки в аппликативном слое, так как оно недостаточно масштабируется и не имеет отношения к случаю, когда вам нужно ограничить набор результатов в БД.

Лучший подход, с которым я столкнулся, предлагается в этот поток, и он полагает, что если вам нужно отсортировать значения в запросе, следует добавить их в набор ключей, а затем запросить ключ с помощью диапазона - указав желаемый ключ и ослабив диапазон значений. Например, если ваш ключ состоит из страны, штата и города:

emit([doc.address.country,doc.address.state, doc.address.city], doc);

Затем вы запрашиваете только страну и получаете бесплатную сортировку по остальным ключевым компонентам:

startkey=["US"]&endkey=["US",{}] 

Если вам также нужно отменить порядок - обратите внимание, что простого определения descending: true будет недостаточно. Вам действительно нужно изменить порядок начала и конца ключа, т.е.:

startkey=["US",{}]&endkey=["US"]

См. больше ссылок на этот большой source.

Ответ 6

Каждое решение выше сломает производительность couchdb, я думаю. Я очень новичок в этой базе данных. Поскольку я знаю, что представления couchdb готовят результаты до того, как будут опрошены. Кажется, нам нужно подготовить результаты вручную. Например, каждый поисковый запрос будет находиться в базе данных с количеством попаданий. И когда кто-то ищет, его поисковые запросы будут проверяться и увеличивать количество попаданий. Когда мы хотим видеть популярность поискового термина, он будет испускать (hitcount, searchterm) пару.

Ответ 7

Ссылка Retrieve_the_top_N_tags кажется сломанной, но я нашел другое решение здесь.

Цитата разработчика, который написал это решение:

вместо того, чтобы возвращать результаты с помощью тега на шаге карты, я бы выбрал каждое появление каждого тега. Затем на этапе уменьшения я вычислил значения агрегации, сгруппированные по тегу, используя хеш, преобразует его в массив, сортирует его и выбирает верхнюю часть.

Как указано в комментариях, единственная проблема была бы в случае длинного хвоста:

Проблема в том, что вы должны быть осторожны с количеством полученных вами тегов; если результат больше 500 байтов, вы будете жаловаться на couchdb, так как "сокращение должно эффективно уменьшаться". 3 или 6 или даже 20 тегов не должны быть проблемой.

Он отлично работал у меня, проверьте ссылку, чтобы увидеть код!