Запросы и фильтрация CouchDB по трем индексированным клавишам - PullRequest
3 голосов
/ 24 августа 2011

Я сейчас пытаюсь упорядочить и отсортировать по ключу с тремя значениями. Но давайте начнем со структуры документа:

{
    _id: "DOCIDGOESHERE01",
    type: "MESSAGE",
    date: "2011-08-24 06:49:02",
    author: "USERIDGOESHERE01",
    receiver: ["USERIDGOESHERE02", "USERIDGOESHERE03"],
    message: "ok let's do this"
}

Основная цель - запросить у couchDB сообщения, отправленные выбранными пользователями одному конкретному пользователю, и упорядочить их по дате. Некоторые сообщения не имеют получателя, который указывает, что они являются общедоступными и могут быть прочитаны кем угодно.

Функция карты, которую я сейчас использую, выглядит следующим образом:

function map(doc) {
    if(doc.receiver.lenth==0)
        emit([doc.date, null, doc.author], doc._id);
    else for(var idx in doc.receiver)
        emit([doc.date, doc.receiver[idx], doc.author], doc._id);
}

При запросе HTTP-интерфейса couchDB я пробовал запросы типа

HTTP GET xxx/messages?key=[{}, "USERIDGOESHERE02", {}]

или

HTTP POST xxx/messages
{
    keys: [
        [{}, "USERIDGOESHERE02", "USERIDGOESHERE01"],
        [{}, "USERIDGOESHERE02", "USERIDGOESHERE03"],
        [{}, "USERIDGOESHERE02", "USERIDGOESHERE04"],
    ]
}

но все они не привели к списку документов, которые я хотел подготовить. Есть ли у вас какие-либо предложения с этой задачей? Или невозможно построить такие отфильтрованные результаты с couchDB? Заранее большое спасибо!

Ответы [ 2 ]

7 голосов
/ 24 августа 2011

Ключи всегда сортируются от наименьшего к наибольшему в одном длинном одномерном списке. (Я пытался описать это интуитивно в Притча о CouchDB , но не знаю, удастся ли мне!)

Как выглядит отсортированный массив от наименьшего к наибольшему? Если вы прочитаете все клавиши в представлении, значение слева изменяется меньше всего; среднее значение меняется больше, чем левое; и правая величина варьируется больше всего. Другими словами, ключи массива сообщают CouchDB: «Первым приоритетом является сортировка по key[0], если он равен, прерыватель связи будет key[1]; если они равны, следующий прерыватель связи будет key[2] и т. Д. ... "

Поэтому вы, вероятно, хотите, чтобы ваши ключи выглядели так:

[ "receiver_1", null      , a_date       ],
[ "receiver_1", "sender_A", some_date    ],
[ "receiver_1", "sender_B", another_date ],
[ "receiver_2", "sender_A", fourth_date  ],
[ "receiver_3", "sender_C", fifth_date   ],

Чтобы найти все сообщения для получателя_1 от sender_B, а также публичные сообщения, вам нужно два запроса: один для пар "receiver_1", null, а другой для "receiver_1", "sender_B". Вы хотите знать любую дату, поэтому вам необходим диапазон строк, которые соответствуют отправителю / получателю. К сожалению, запрос HTTP POST не поддерживает это.

Вы можете просто запросить каждого выбранного отправителя (даже все одновременно, используя потоки или асинхронное программирование). Получатель и отправитель известны, и этот пример допускает диапазон от наименьшего значения (null) до наибольшего ({}), который будет включать все даты.

?startkey=["receiver_1",null,null]&endkey=["receiver_1",null,{}]
?startkey=["receiver_1","sender_B",null]&endkey=["receiver_1","sender_B",{}]

Другой вариант - упростить ключи и убрать даты.

[ "receiver_1", null      ],
[ "receiver_1", "sender_A"],
[ "receiver_1", "sender_B"],
[ "receiver_2", "sender_A"],
[ "receiver_3", "sender_C"],
[ "receiver_3", "sender_C"],
[ "receiver_3", "sender_C"],
[ "receiver_3", "sender_C"],
[ "receiver_3", "sender_C"],

Теперь вы можете снова запросить HTTP POST API. Сообщения будут возвращаться , а не , упорядоченные по дате. Это не так уж плохо, вы можете отсортировать их на клиенте (или функцию _list). И помните, даже в моем первом примере даты также не сортируются идеально.

5 голосов
/ 24 августа 2011

Я думаю, что вы хотите;

emit([doc.author, doc.receiver[idx], doc.date], null);

Затем вы можете запросить с помощью

startkey=["USERID1","USERID2"]&endkey=["USERID1","USERID2",{}]

, чтобы вернуть все документы, отправленные USERID1 в USERID2 в порядке дат.{} является пустым объектом и, по правилам сортировки CouchDB, будет сортировать больше, чем любое число или строка, поэтому диапазон здесь гарантированно включает все возможные даты.

Наконец, я отмечу, что CouchDBне поддерживает подстановочные знаки.

...