CouchDB сортировка и фильтрация в одном представлении - PullRequest
32 голосов
/ 22 июля 2010

Я пытаюсь использовать CouchDB для нового приложения, и мне нужно создать представление, которое сортирует по нескольким полям, а также фильтрует по нескольким полям.Вот пример документа, я оставил _id и _rev, чтобы сэкономить при вводе.

{
    "title": "My Document",
    "date": 1279816057,
    "ranking": 5,
    "category": "fun",
    "tags": [
        "couchdb",
        "technology"
    ],
}

Из документации я узнал, что могу легко создать вид, сортирующий по полюНапример, рейтингВсе одновременно.Я хочу фильтровать по категории, а также по тегу.Я должен быть в состоянии отфильтровать только документы с категорией «веселья» и тегом «couchdb».Я хочу отсортировать отфильтрованные результаты по рейтингу в порядке убывания, затем по дате в порядке возрастания, а затем по заголовку в алфавитном порядке.

Как создать одно представление, которое объединит всю эту сортировку и фильтрацию?

1 Ответ

48 голосов
/ 23 июля 2010

Для передачи более чем одного фрагмента данных в ключе вы должны прочитать о Сложные ключи .Скорее всего, вы получите emit() ключ, представляющий собой массив, состоящий из категории и тега.Например ...

function(doc) {
  for(var i = 0; i < doc.tags.length; i++)
    emit([doc.category, doc.tags[i]], doc);
}

Теперь, когда вы запросите ?key=["fun", "couchdb"], вы получите все элементы в категории веселья с тегом "couchdb".Или, если вы хотите, чтобы все элементы в категории веселья, независимо от их тега, вы можете запросить в диапазоне: ?startkey=["fun"]&endkey=["fun", {}].Просто помните, что если ваш элемент имеет несколько тегов, вы получите его несколько раз в результатах (потому что вы emit() делали документ один раз на тег).

Чтобы выполнить дополнительный шаг сортировки по рейтингу, дата и заголовок вы добавите еще два элемента в ваш массив: целое число и рейтинг, дату или заголовок.Помните, что вы можете emit() более одного раза для каждой функции карты.Пример функции карты ...

function(doc) {
  for(var i = 0; i < doc.tags.length; i++)
  {
     emit([doc.category, doc.tags[i], 0, doc.ranking], doc);
     emit([doc.category, doc.tags[i], 1, doc.title], doc);
     emit([doc.category, doc.tags[i], 2, doc.date], doc);
  }
}

Теперь ваша ключевая структура: ["category", "tag", 0 ... 2, rank/title/date]

Вы в основном группируете все рейтинги под 0, названия под 1 и даты под2. Конечно, вы передаете много данных, так что вы можете разбить каждую из этих групп на отдельные представления в вашем проектном документе или только вернуть документ _id в качестве значения (emit([ ...], doc._id);).

Получить все в категории "веселья" с тегом "couchdb" (по возрастанию):

?startkey=["fun", "couchdb"]&endkey=["fun", "couchdb", {}, {}]

Получить все в категории "развлечения" с тегом "couchdb" (по убыванию):

?startkey=["fun", "couchdb", {}, {}]&endkey=["fun", "couchdb"]&descending=true

Получить только рейтинги в категории веселья с тегом couchdb (по возрастанию):

?startkey=["fun", "couchdb", 0]&endkey=["fun", "couchdb", 0, {}]

Получить только рейтинг в категории "веселья" стег "couchdb" (по убыванию):

?startkey=["fun", "couchdb", 0, {}]&endkey=["fun", "couchdb", 0]&descending=true

Надеюсь, это поможет.Сложные ключи начинают действительно показывать, насколько мощно Map / Reduce для нарезки и нарезки данных.

Cheers.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...