Spec-Zone.ru › CouchDB 3.5

Nouveau

Предупреждение

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

Индексы Nouveau позволяют выполнять запросы к базе данных с использованием синтаксиса Lucene Query Parser. Индекс nouveau использует одно или несколько полей ваших документов. С помощью индекса nouveau можно выполнять запросы и находить документы по содержащемуся в них содержимому.

Предупреждение

Nouveau не может работать без функционирующего сервера Nouveau. Подробности см. в разделе Установка сервера Nouveau.

Чтобы создать индекс nouveau, добавьте функцию JavaScript в документ дизайна базы данных. Индекс создаётся после обработки одного поискового запроса или после обнаружения сервером обновления документа. Функция index принимает следующие параметры:

  1. Тип поля — тип поля: string, text, double или stored. Дополнительную информацию см. в разделе Типы полей.

  2. Имя поля — имя поля, которое нужно использовать при запросах к индексу. Если задать для этого параметра значение default, запрос будет выполняться по этому полю, если в синтаксисе запроса поле не указано.

  3. Данные, которые требуется индексировать, например doc.address.country.

  4. (Необязательно) Третий параметр содержит следующее поле: store.

По умолчанию ответ индекса nouveau содержит 25 строк. Количество возвращаемых совпадений можно изменить с помощью параметра limit. Каждый ответ содержит поле bookmark. Значение поля bookmark можно включать в последующие запросы, чтобы получать результаты, находящиеся глубже в наборе результатов.

Пример документа дизайна, определяющего индекс nouveau:

{
    "_id": "_design/nouveau_example",
    "nouveau": {
        "animals": {
            "index": "function(doc){ ... }"
        }
    }
}

Индекс nouveau наследует тип секционирования из поля options.partitioned документа дизайна, в котором он содержится.

Типы полей

В настоящее время Nouveau поддерживает четыре типа полей, каждый из которых отличается семантикой.

Текст

Текстовое поле — наиболее распространённый тип поля. Значение поля анализируется во время индексирования, что позволяет эффективно выполнять поиск по отдельным словам в нём (а также с помощью подстановочных знаков, регулярных выражений и т. д.). Этот тип поля не подходит для сортировки, запросов по диапазону и фасетного поиска.

Строка

В строковом поле значение индексируется как один токен без анализа (то есть без приведения регистра, удаления распространённых суффиксов и т. д.). Этот тип поля рекомендуется использовать для сортировки и фасетного поиска. Выполнять поиск по строковым полям можно, но в определении индекса для этого поля необходимо указать анализатор keyword, чтобы запросы не анализировались.

Число с плавающей точкой двойной точности

Для поля типа double требуется числовое значение. Оно подходит для сортировки, запросов по диапазону и фасетного поиска по диапазонам.

Хранимое

Хранимое поле сохраняет значение поля в индексе без анализа. Это значение возвращается в результатах поиска, но по хранимому полю нельзя выполнять поиск, сортировку, запросы по диапазону или фасетный поиск.

Предупреждение

Тип любого конкретного поля определяется при первом вызове индексирования. Попытки индексировать значение другого типа в том же поле приведут к исключению и помешают построению индекса.

Функции индексирования

Попытка индексировать данные с помощью несуществующего поля приведёт к ошибке. Чтобы избежать этой проблемы, используйте соответствующее защитное условие.

Примечание

Функции индексирования выполняются в среде с ограниченным объёмом памяти, и сам документ занимает часть этой памяти. Стек вашего кода и документ должны помещаться в эту память. Иными словами, для индексирования документ необходимо загрузить. Максимальный размер документа — 64 МБ.

Функция, содержащаяся в поле индекса, — это функция JavaScript, вызываемая для каждого документа в базе данных. Она принимает документ в качестве параметра, извлекает из него данные, а затем вызывает функцию, определённую в поле index, чтобы индексировать эти данные.

Функция index принимает четыре параметра, третий из которых необязателен.

  1. Первый параметр — тип поля.

  2. Второй параметр — имя поля, которое вы собираетесь использовать при запросах к индексу и указывать в синтаксисе Lucene в последующих запросах. Пример приведён в следующем запросе:

    q=color:red

    Имя поля Lucene color — это первый параметр функции index.

    Если при определении имени используется специальное значение "default", указывать имя поля во время выполнения запроса не требуется. Благодаря этому запрос можно упростить:

    q=red
  3. Третий параметр — индексируемые данные. При индексировании данных учитывайте следующее:

    • Эти данные должны быть строкой, числом или логическим значением. Другие типы приведут к ошибке при вызове функции индексирования.

    • Если во время выполнения функции возникнет ошибка по этой или другой причине, документ не будет добавлен в поисковый индекс.

  4. Четвёртый, необязательный параметр — объект JavaScript со следующими полями:

    Функция индексирования (необязательный параметр)

    • store — если значение равно true, значение возвращается в результатах поиска; в противном случае оно не возвращается. Допустимые значения: true или false. Значение по умолчанию — false.

    Примечание

    Если не задать параметр store, результаты индексирования данных документа не будут возвращаться в ответ на запрос.

Пример функции поискового индексирования:

function(doc) {
    if (typeof(doc.min_length) == 'number') {
        index("double", "min_length", doc.min_length, {"store": true});
    }
    if (typeof(doc.diet) == 'string') {
        index("string", "diet", doc.diet, {"store": true});
    }
    if (typeof(doc.latin_name) == 'string') {
        index("string", "latin_name", doc.latin_name, {"store": true});
    }
    if (typeof(doc.class) == 'string') {
        index("string", "class", doc.class, {"store": true});
    }
}

Защитные условия индексирования

Ошибки времени выполнения в функции индексирования приводят к тому, что документ вообще не индексируется. Ниже описаны наиболее распространённые ошибки времени выполнения;

Пример отсутствия проверки существования индексируемого значения:

Предупреждение

пример некорректного кода

index("double", "min_length", doc.min_length, {"store": true});

Для документов без значения min_length этот вызов индексирования передаст undefined в качестве значения. Проверочная функция nouveau отклонит его, и документ не будет индексирован.

Пример отсутствия проверки существования вложенного индексируемого значения:

Предупреждение

пример некорректного кода

if (doc.foo.bar) {
    index("string", "bar", doc.foo.bar, {"store": true});
}

Этот некорректный пример завершается ошибкой по другой причине, если doc.foo не существует: вычисление doc.foo.bar вызывает исключение.

if (doc.foo && typeof(doc.foo) == 'object' && typeof(doc.foo.bar == 'string')) {
    index("string", "bar", doc.foo.bar, {"store": true});
}

В этом примере правильно проверяется, что doc.foo является объектом, а его элемент bar — строкой.

Пример проверки существования индексируемого значения с запретом допустимых значений false:

Предупреждение

пример некорректного кода

if (doc.min_length) {
  index("double", "min_length", doc.min_length, {"store": true});
}

Мы исправляем предыдущую ошибку, чтобы документы без min_length индексировались (при условии, что есть другие вызовы индексирования для значений, которые существуют), но случайно запрещаем индексирование поля min_length, если doc.min_length имеет значение 0.

if (typeof(doc.min_length == 'number')) {
  index("double", "min_length", doc.min_length, {"store": true});
}

В этом корректном примере гарантируется индексирование любого документа, в котором min_length является числом.

Анализаторы

Анализаторы преобразуют текстовый ввод в tokens, по которым можно выполнять поиск. Обычно анализаторы используют разные правила разбиения входных данных на токены: они могут переводить весь текст в нижний регистр, пропускать целые слова (обычно настолько распространённые, что вряд ли полезны для поиска) или пропускать части слов (например, удалять ing суффиксы в английском языке):

Мы предоставляем множество анализаторов Lucene, а один создали самостоятельно (simple_asciifolding);

  • arabic

  • armenian

  • basque

  • bulgarian

  • catalan

  • chinese

  • cjk

  • classic

  • czech

  • danish

  • dutch

  • email

  • english

  • finnish

  • french

  • galician

  • german

  • hindi

  • hungarian

  • indonesian

  • irish

  • italian

  • japanese

  • keyword

  • latvian

  • norwegian

  • persian

  • polish

  • portugese

  • romanian

  • russian

  • simple

  • simple_asciifolding

  • spanish

  • standard

  • swedish

  • thai

  • turkish

  • whitespace

Пример документа анализатора:

{
    "_id": "_design/analyzer_example",
    "nouveau": {
        "INDEX_NAME": {
            "index": "function (doc) { ... }",
            "default_analyzer": "$ANALYZER_NAME"
        }
    }
}

Анализаторы полей

При необходимости для конкретного поля можно указать другой анализатор.

Пример определения разных анализаторов для разных полей:

{
    "_id": "_design/analyzer_example",
    "nouveau": {
        "INDEX_NAME": {
            "default_analyzer": "english",
            "field_analyzers": {
                "spanish": "spanish",
                "german": "german"
            },
            "index": "function (doc) { ... }"
        }
    }
}

Проверка токенизации анализатора

Результаты токенизации анализатора можно проверить, отправив примеры данных на конечную точку _nouveau_analyze.

Пример проверки анализатора keyword с помощью HTTP:

POST /_nouveau_analyze HTTP/1.1
Content-Type: application/json
{"analyzer":"keyword", "text":"ablanks@renovations.com"}

Пример проверки анализатора keyword из командной строки:

curl 'https://$HOST:5984/_nouveau_analyze' -H 'Content-Type: application/json'
    -d '{"analyzer":"keyword", "text":"ablanks@renovations.com"}'

Результат проверки анализатора keyword:

{
    "tokens": [
        "ablanks@renovations.com"
    ]
}

Пример проверки анализатора standard с помощью HTTP:

POST /_nouveau_analyze HTTP/1.1
Content-Type: application/json
{"analyzer":"standard", "text":"ablanks@renovations.com"}

Пример проверки анализатора standard из командной строки:

curl 'https://$HOST:5984/_nouveau_analyze' -H 'Content-Type: application/json'
    -d '{"analyzer":"standard", "text":"ablanks@renovations.com"}'

Результат проверки анализатора standard:

{
    "tokens": [
        "ablanks",
        "renovations.com"
    ]
}

Запросы

После создания поискового индекса можно выполнять запросы к нему.

  • Выполните запрос к разделу с помощью: GET /$DATABASE/_partition/$PARTITION_KEY/_design/$DDOC/_nouveau/$INDEX_NAME

  • Выполните глобальный запрос с помощью: GET /$DATABASE/_design/$DDOC/_nouveau/$INDEX_NAME

Укажите поисковый запрос с помощью параметра q.

Пример запроса к секционированному индексу с помощью HTTP:

GET /$DATABASE/_partition/$PARTITION_KEY/_design/$DDOC/_nouveau/$INDEX_NAME?include_docs=true&q=*:*&limit=1 HTTP/1.1
Content-Type: application/json

Пример запроса к глобальному индексу с помощью HTTP:

GET /$DATABASE/_design/$DDOC/_nouveau/$INDEX_NAME?include_docs=true&q=*:*&limit=1 HTTP/1.1
Content-Type: application/json

Пример запроса к секционированному индексу из командной строки:

curl https://$HOST:5984/$DATABASE/_partition/$PARTITION_KEY/_design/$DDOC/
_nouveau/$INDEX_NAME?include_docs=true\&q=*:*\&limit=1 \

Пример запроса к глобальному индексу из командной строки:

curl https://$HOST:5984/$DATABASE/_design/$DDOC/_nouveau/$INDEX_NAME?
include_docs=true\&q=*:*\&limit=1 \

Параметры запроса

Полный список параметров запроса приведён в справочнике API.

Примечание

Не используйте вместе параметры bookmark и update. Эти параметры ограничивают выбор реплик шардов, используемых для ответа. При совместном использовании они могут вызвать проблемы при попытке связаться с медленными или недоступными репликами.

Релевантность

Если запрос может вернуть несколько результатов, их можно отсортировать. По умолчанию порядок сортировки определяется «релевантностью».

Релевантность определяется согласно оценке Apache Lucene. Например, если выполнить поиск по слову example в простой базе данных, оно может встретиться в двух документах. Если в одном документе слово example встречается 10 раз, а во втором — только два раза, первый документ считается более «релевантным».

Если параметр sort не задан, по умолчанию используется релевантность. Сначала возвращаются совпадения с наивысшей оценкой.

Если задать параметр sort, совпадения будут возвращены в указанном порядке, без учёта релевантности.

Если требуется использовать параметр sort и при этом включить сортировку по релевантности в результаты поиска, укажите специальные поля -<score> или <score> в параметре sort.

Отправка поисковых запросов методом POST

Вместо HTTP-метода GET можно использовать POST. Главное преимущество запросов POST заключается в том, что они могут содержать тело запроса, позволяя передать запрос в виде объекта JSON. Каждому параметру в строке запроса GET соответствует поле объекта JSON в теле запроса.

Пример отправки поискового запроса методом POST с помощью HTTP:

POST /db/_design/ddoc/_nouveau/searchname HTTP/1.1
Content-Type: application/json

Пример отправки поискового запроса методом POST из командной строки:

curl 'https://$HOST:5984/db/_design/ddoc/_nouveau/searchname' -X POST -H 'Content-Type: application/json' -d @search.json

Пример документа JSON, содержащего поисковый запрос:

{
    "q": "index:my query",
    "sort": "foo",
    "limit": 3
}

Синтаксис запросов

Синтаксис поисковых запросов CouchDB основан на синтаксисе Lucene. Поисковые запросы имеют вид name:value; если имя не указано, используется поле по умолчанию, как показано в следующих примерах:

Примеры выражений поисковых запросов:

// Birds
class:bird
// Animals that begin with the letter "l"
l*
// Carnivorous birds
class:bird AND diet:carnivore
// Herbivores that start with letter "l"
l* AND diet:herbivore
// Medium-sized herbivores
min_length:[1 TO 3] AND diet:herbivore
// Herbivores that are 2m long or less
diet:herbivore AND min_length:[* TO 2]
// Mammals that are at least 1.5m long
class:mammal AND min_length:[1.5 TO *]
// Find "Meles meles"
latin_name:"Meles meles"
// Mammals who are herbivore or carnivore
diet:(herbivore OR omnivore) AND class:mammal
// Return all results
*:*

Запросы к нескольким полям можно логически объединять, а группы и поля можно дополнительно группировать. Доступны следующие логические операторы с учётом регистра: AND, +, OR, NOT и -. Запросы по диапазону можно выполнять для строк и чисел.

Для нечёткого поиска можно добавить к запросу ~, чтобы найти термины, похожие на поисковый термин. Например, look~ находит термины book и took.

Примечание

Если нижняя и верхняя границы диапазона — строки, состоящие только из цифр, они интерпретируются как числа, а не как строки. Например, при поиске с запросом mod_date:["20170101" TO "20171231"] результаты включают документы, в которых mod_date находится между числовыми значениями 20170101 и 20171231, а не между строками «20170101» и «20171231».

Важность поискового термина можно изменить, добавив ^ и положительное число. Это изменение повышает или понижает релевантность совпадений, содержащих термин, пропорционально степени указанного коэффициента. Значение по умолчанию — 1, то есть сила совпадения не увеличивается и не уменьшается. Десятичное значение от 0 до 1 снижает важность и ослабляет совпадение. Значение больше единицы повышает важность и усиливает совпадение.

Поддерживается поиск с подстановочными знаками как для одного (?), так и для нескольких (*) символов. Например, dat? соответствует date и data, тогда как dat* соответствует date, data, database и dates. Подстановочные знаки должны стоять после поискового термина.

Используйте *:*, чтобы вернуть все результаты.

Для поиска по следующим символам их необходимо экранировать:

+ - && || ! ( ) { } [ ] ^ " ~ * ? : \ /

Чтобы экранировать один из этих символов, поставьте перед ним обратную косую черту (\).

Ответ на поисковый запрос содержит поле order для каждого результата. Поле order — это массив, первый элемент которого содержит поле или поля, указанные в параметре sort. См. параметр sort. Если параметр sort не указан в запросе, поле order содержит оценку релевантности Lucene.

Фасетный поиск

Поиск Nouveau также поддерживает фасетный поиск, позволяя быстро и легко находить сводную информацию о совпадениях. С помощью специального синтаксиса запроса ?q=*:* можно выбрать все документы, а затем уточнить запрос с помощью возвращённых фасетов.

Пример поискового запроса:

function(doc) {
    index("string", "type", doc.type);
    index("double", "price", doc.price);
}

Для использования фасетов все документы в индексе должны содержать все поля, для которых включён фасетный поиск. Если в документах отсутствуют какие-либо из этих полей, вы получите ошибку bad_request со следующей причиной: «Поле field_name не существует». Если не каждый документ содержит все поля для фасетов, создайте отдельные индексы для каждого поля. Если отдельные индексы для каждого поля не создаются, включайте только документы, содержащие все поля. Убедитесь, что поля существуют в каждом документе, используя одно выражение if.

Параметр запроса top_n задаёт количество возвращаемых фасетов для каждой группы. По умолчанию возвращается 10, максимум — 1000.

Пример оператора if для проверки наличия обязательных полей в каждом документе:

if (typeof doc.town == "string" && typeof doc.name == "string") {
    index("string", "town", doc.town);
    index("string", "name", doc.name);
   }

Подсчёты

Примечание

Параметр counts доступен только для глобальных запросов.

Синтаксис фасета counts принимает список полей и возвращает количество результатов запроса для каждого уникального значения каждого указанного поля.

Примечание

Операция count работает только в том случае, если индексированные значения являются строками. Индексированные значения не могут иметь разные типы. Например, если проиндексировано 100 строк и одно число, индекс нельзя использовать для операций count. Проверить тип можно с помощью оператора typeof, а преобразовать его — с помощью функций parseInt, parseFloat или .toString().

Пример запроса с использованием синтаксиса фасета counts:

?q=*:*&counts=["type"]

Пример ответа после использования синтаксиса фасета counts:

{
    "total_rows":100000,
    "bookmark":"g...",
    "rows":[...],
    "counts":{
        "type":{
            "sofa": 10,
            "chair": 100,
            "lamp": 97
        }
    }
}

Диапазоны

Примечание

Параметр ranges доступен только для глобальных запросов.

Значение параметра диапазона — объект JSON, где имена полей соответствуют полям типа double, а значения полей представляют собой массивы объектов JSON. Объекты должны содержать значения label, min и max (соответственно типа string, double и double), а также необязательные свойства min_inclusive и max_inclusive (если они не указаны, используется значение true).

Пример запроса, использующего фасетный поиск для совпадающих диапазонов:

?q=*:*&ranges={"price":[{"label":"cheap","min":0,"max":"100","max_inclusive":false},{"label":"expensive","min":100}]}

Пример результатов проверки диапазонов при фасетном поиске:

{
    "total_rows":100000,
    "bookmark":"g...",
    "rows":[...],
    "ranges": {
        "price": {
            "expensive": 278682,
            "cheap": 257023
        }
    }
}

Copyright © 2025 The Apache Software Foundation — Licensed under the Apache License 2.0
https://docs.couchdb.org/en/3.5.1/ddocs/nouveau.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API