2010-07-22 4 views
29

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

{ 
    "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». Я хочу отсортировать результаты фильтрации по ранжированию в порядке убывания, затем по дате в порядке возрастания, затем по названию в алфавитном порядке.

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

ответ

45

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

Получить все в "забавной" категории с "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.

+0

Спасибо, что это действительно полезно, но мне просто нужно немного помочь. Так как он издает одни и те же документы снова и снова, как мне заставить его просто дать мне каждый документ один раз? – Apreche

+1

Вы не можете, если только вы не разбиваете каждую из этих групп на свое собственное видение. Например,/_design/articles/_view/byRanking,/_design/articles/_view/byDate и т. Д. Если вы хотите сохранить все в этом одном представлении, вам придется управлять данными в вашем клиенте. Или вы могли бы следить за тем, что я говорил только о возврате _id или null в качестве значения, так как вы могли бы сделать второй звонок, чтобы получить документ один раз. –

+0

Ой, подождите, неважно. Я понял. Я думаю, вы слегка неправильно поняли то, что я хотел. Я хочу сортировать по ранжированию, дате и названию одновременно. В SQL это будет «порядок по ранжированию asc, date desc, title asc». Я могу сделать это, выполнив только один emit и использую ключ запуска и конечный ключ для фильтрации, и заказ уже будет выполнен. Благодаря! – Apreche

Смежные вопросы