Сортировка представлений
Основы
Функции представлений задают ключ и значение, возвращаемые для каждой строки. CouchDB сортирует строки представления по этому ключу. В следующем примере свойство LastName служит ключом, поэтому результат будет отсортирован по LastName:
function(doc) {
if (doc.Type == "customer") {
emit(doc.LastName, {FirstName: doc.FirstName, Address: doc.Address});
}
} CouchDB позволяет использовать в качестве ключей произвольные структуры JSON. Для точного управления сортировкой и группировкой можно использовать массивы JSON.
Примеры
Следующий остроумный прием позволяет получить и документы клиентов, и документы заказов. Ключ состоит из _id клиента и токена сортировки. Поскольку ключ документов заказов начинается с _id документа клиента, все заказы будут отсортированы по клиентам. Поскольку токен сортировки для клиентов меньше токена для заказов, документ клиента будет располагаться перед связанными с ним заказами. Значения 0 и 1 для токена сортировки выбраны произвольно.
function(doc) {
if (doc.Type == "customer") {
emit([doc._id, 0], null);
} else if (doc.Type == "order") {
emit([doc.customer_id, 1], null);
}
} Чтобы вывести конкретного клиента с _id XYZ и все заказы этого клиента, ограничьте диапазоны startkey и endkey так, чтобы они охватывали только документы для _id этого клиента:
startkey=["XYZ"]&endkey=["XYZ", {}] Не рекомендуется возвращать сам документ в представлении. Вместо этого, чтобы включить содержимое документов при запросе представления, запросите представление с параметром ?include_docs=true.
Сортировка по датам
Может быть удобно хранить атрибуты даты в удобочитаемом формате (то есть как строку), но при этом сортировать по дате. Для этого можно преобразовать дату в число в функции emit(). Например, для документа с атрибутом created_at, равным 'Wed Jul 23 16:29:21 +0100 2013', следующая функция emit выполнит сортировку по дате:
emit(Date.parse(doc.created_at).getTime(), null);
Кроме того, если используется формат даты, который сортируется лексикографически, например "2013/06/09 13:52:11 +0000", можно просто
emit(doc.created_at, null);
и обойтись без преобразования. Бонус: этот формат даты совместим с анализатором дат JavaScript, поэтому в клиентском JavaScript можно использовать new Date(doc.created_at), чтобы упростить сортировку дат в браузере.
Диапазоны строк
Если нужны начальный и конечный ключи, охватывающие все строки с заданным префиксом, лучше использовать символ Юникода с высоким значением, а не суффикс 'ZZZZ'.
То есть вместо:
startkey="abc"&endkey="abcZZZZZZZZZ"
следует использовать:
startkey="abc"&endkey="abc\ufff0"
Спецификация сортировки
Этот раздел основан на функции view_collation из view_collation.js:
// special values sort before all other types
null
false
true
// then numbers
1
2
3.0
4
// then text, case sensitive
"a"
"A"
"aa"
"b"
"B"
"ba"
"bb"
// then arrays. compared element by element until different.
// Longer arrays sort after their prefixes
["a"]
["b"]
["b","c"]
["b","c", "a"]
["b","d"]
["b","d", "e"]
// then object, compares each key value in the list until different.
// larger objects sort after their subset objects.
{a:1}
{a:2}
{b:1}
{b:2}
{b:2, a:1} // Member order does matter for collation.
// CouchDB preserves member order
// but doesn't require that clients will.
// this test might fail if used with a js engine
// that doesn't preserve order
{b:2, c:2} Сравнение строк выполняется с помощью ICU, реализующей алгоритм сортировки Юникода, который обеспечивает сортировку ключей в словарном порядке. Это может привести к неожиданным результатам, если вы рассчитывали на порядок ASCII. Обратите внимание:
Все символы располагаются перед цифрами и буквами (в том числе «старшие» символы, например тильда,
0x7e)Различающиеся последовательности букв сравниваются без учета регистра, поэтому
a < aa, а такжеA < aaиa < AAОдинаковые последовательности букв сравниваются с учетом регистра: строчные буквы идут перед прописными, поэтому
a < A
Последовательность сортировки 7-битных символов ASCII можно продемонстрировать так:
require 'rubygems'
require 'restclient'
require 'json'
DB="http://adm:pass@127.0.0.1:5984/collator"
RestClient.delete DB rescue nil
RestClient.put "#{DB}",""
(32..126).each do |c|
RestClient.put "#{DB}/#{c.to_s(16)}", {"x"=>c.chr}.to_json
end
RestClient.put "#{DB}/_design/test", <<EOS
{
"views":{
"one":{
"map":"function (doc) { emit(doc.x,null); }"
}
}
}
EOS
puts RestClient.get("#{DB}/_design/test/_view/one") Получается следующая последовательность сортировки:
` ^ _ - , ; : ! ? . ' " ( ) [ ] { } @ * / \ & # % + < = > | ~ $ 0 1 2 3 4 5 6 7 8 9
a A b B c C d D e E f F g G h H i I j J k K l L m M n N o O p P q Q r R s S t T u U v V w W x X y Y z Z Диапазоны ключей
Будьте особенно внимательны при запросе диапазонов ключей. Например, запрос:
startkey="Abc"&endkey="AbcZZZZ"
найдет «ABC» и «abc1», но не «abc». Это связано с тем, что UCA сортирует так:
abc < Abc < ABC < abc1 < AbcZZZZZ
Чтобы избежать проблем в большинстве приложений, следует перевести startkey в нижний регистр:
startkey="abc"&endkey="abcZZZZZZZZ"
найдет все ключи, начинающиеся с [aA][bB][cC]
Составные ключи
Запрос startkey=["foo"]&endkey=["foo",{}] найдет большинство ключей-массивов, у которых первым элементом является «foo», например ["foo","bar"] и ["foo",["bar","baz"]]. Однако он не найдет ["foo",{"an":"object"}]
_all_docs
Представление _all_docs — особый случай: для идентификаторов документов оно использует сортировку ASCII, а не UCA:
startkey="_design/"&endkey="_design/ZZZZZZZZ"
не найдет _design/abc, потому что в последовательности ASCII «Z» идет перед «a». Лучше использовать следующий вариант:
startkey="_design/"&endkey="_design0"
Нативная сортировка
Чтобы немного повысить производительность представлений, можно указать "options":{"collation":"raw"} в определении представления для использования нативной сортировки Erlang, особенно если UCA не требуется. В этом случае последовательность сортировки будет другой:
1
false
null
true
{"a":"a"},
["a"]
"a" Имейте в виду, что {} больше не подходит в качестве «верхнего» ключа-маркера. Вместо него используйте строку, например "\ufff0".
Copyright © 2025 The Apache Software Foundation — Licensed under the Apache License 2.0
https://docs.couchdb.org/en/3.5.1/ddocs/views/collation.html