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

Сортировка и фильтрация CouchDB в одном представлении

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

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

Из документации я узнал, что я могу легко создать представление, которое сортируется по полю, например ранжированию.

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

Я также узнал, что я могу легко фильтровать по таким полям, как категория

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

http://127.0.0.1:5984/database/_design/filter/_view/filter?key=%22fun%22

Моя проблема в том, что мне нужно делать кучу этих вещей одновременно. Я хочу фильтровать на основе категории, а также тега. Я должен иметь возможность фильтровать только документы с категорией "fun" и тегом "couchdb". Я хочу отсортировать результаты фильтрации по ранжированию в порядке убывания, затем по дате в порядке возрастания, затем по названию в алфавитном порядке.

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

4b9b3361

Ответ 1

Для испускания более одного фрагмента данных в ключе, вы хотите прочитать Комплексные ключи. Скорее всего, вы получите 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() 'd doc один раз за тег).

Чтобы перейти к дополнительному шагу сортировки по рейтингу, дате и названию, вы добавите еще два элемента в ваш массив: целое число и либо рейтинг, дата, либо название. Помните, что вы можете 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);).

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

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

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

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

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

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

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

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

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

Приветствия.