Статьи

Интеграция Lucene Search в приложение

Эта статья является частью нашего академического курса под названием Apache Lucene Fundamentals .

В этом курсе вы познакомитесь с Lucene. Вы поймете, почему такая библиотека важна, а затем узнаете, как работает поиск в Lucene. Кроме того, вы узнаете, как интегрировать Lucene Search в ваши собственные приложения, чтобы обеспечить надежные возможности поиска. Проверьте это здесь !

1. Введение

Java Lucene предоставляет довольно мощный язык запросов для выполнения операций поиска в большом количестве данных.

Запрос разбит на термины и операторы. Есть три типа терминов: отдельные термины , фразы и подзапросы . Один термин — это одно слово, такое как «тест» или «привет». Фраза — это группа слов, заключенная в двойные кавычки, такие как «привет Долли». Подзапрос — это запрос, заключенный в круглые скобки, например, «(привет привет)».

Lucene поддерживает поля данных. При выполнении поиска вы можете либо указать поле, либо использовать поле по умолчанию. Имена полей зависят от индексированных данных, а поле по умолчанию определяется текущими настройками.

2. Разбор строки запроса

Задача анализатора запросов — преобразовать строку запроса, отправленную пользователем, в объекты запроса.

Запрос используется анализатором запросов, который анализирует его содержимое. Вот пример:

1
2
3
4
5
6
{
    "query_string" : {
        "default_field" : "content",
        "query" : "this AND that OR thus"
    }
}

Параметры верхнего уровня query_string включают в себя:

параметр Описание
query Фактический запрос для анализа.
default_field Поле по умолчанию для условий запроса, если префиксное поле не указано. По умолчанию используются index.query.default_field индекса index.query.default_field , которые в свою очередь по умолчанию равны _all.
default_operator Оператор по умолчанию используется, если не указан явный оператор. Например, с оператором по умолчанию OR, столица запроса Венгрии переводится в заглавную букву OR из OR Венгрии, а с оператором по умолчанию AND, тот же запрос транслируется в заглавную букву AND из AND Венгрии. Значением по умолчанию является ИЛИ.
analyzer Имя анализатора, используемого для анализа строки запроса.
allow_leading_wildcard Когда установлено, * или? разрешены в качестве первого символа. По умолчанию true.
lowercase_expanded_terms Должны ли термины подстановочных, префиксных, нечетких и диапазонных запросов автоматически вводиться в нижнем регистре или нет (поскольку они не анализируются). По умолчанию это правда.
enable_position_increments Установите в значение true, чтобы включить приращение позиции в запросах результатов. По умолчанию true.
fuzzy_max_expansions Управляет количеством терминов, которые будут расширены нечеткими запросами. По умолчанию 50
fuzziness Установите нечеткость для нечетких запросов. По умолчанию установлено значение AUTO.
fuzzy_prefix_length Установите длину префикса для нечетких запросов. По умолчанию 0.
phrase_slop Устанавливает отстой по умолчанию для фраз. Если ноль, то требуется точное совпадение фразы. Значение по умолчанию 0.
boost Устанавливает значение повышения запроса. По умолчанию 1.0.
analyze_wildcard По умолчанию термины подстановочных знаков в строке запроса не анализируются. Установив для этого значения значение true, мы сделаем все возможное, чтобы проанализировать их.
auto_generate_phrase_queries По умолчанию false.
minimum_should_match Значение, определяющее, сколько предложений «следует» в результирующем логическом запросе должно совпадать. Это может быть абсолютное значение (2), процент (30%) или их комбинация.
lenient Если установлено значение true, сбои на основе формата (например, предоставление текста в числовое поле) будут игнорироваться.
locale [1.1.0] Добавлен в 1.1.0.Locale, который должен использоваться для преобразования строк. По умолчанию ROOT.

Таблица 1

Когда генерируется многоточечный запрос, можно контролировать, как он переписывается, используя параметр rewrite .

2.1. Правила QueryParser

Предположим, вы ищете в Интернете страницы, содержащие слова java и net, но не слово dot. Что если поисковые системы заставят вас напечатать что-то вроде следующего для этого простого запроса?

1
2
3
4
BooleanQuery query = new BooleanQuery();
query.add(new TermQuery(new Term("contents","java")), true, false);
query.add(new TermQuery(new Term("contents", "net")), true, false);
query.add(new TermQuery(new Term("contents", "dot")), false, true);

Это было бы настоящим тормозом. К счастью, Google, Nutch и другие поисковые системы более дружественны, позволяя вам вводить что-то более лаконичное: java AND net NOT dot Сначала мы посмотрим, что нужно для использования QueryParser в приложении.

2.2. Использование QueryParser

Использование QueryParser довольно просто. Необходимы три вещи: выражение, имя поля по умолчанию, которое будет использоваться для неквалифицированных полей в выражении, и анализатор для частей выражения. Спецификаторы выбора полей обсуждаются в разделе синтаксиса запроса. Анализ, специфичный для анализа запросов, описан в разделе «Анализ паралича». Теперь давайте разберем выражение:

1
2
String humanQuery = getHumanQuery();
Query query = QueryParser.parse(humanQuery, "contents", new StandardAnalyzer());

После того, как вы получили объект Query , поиск выполняется так же, как если бы запрос был создан непосредственно через API. Вот полный метод для поиска существующего индекса с помощью введенной пользователем строки запроса и отображения результатов на консоли:

01
02
03
04
05
06
07
08
09
10
11
12
public static void search(File indexDir, String q) throws Exception{
Directory fsDir = FSDirectory.getDirectory(indexDir, false);
 IndexSearcher is = new IndexSearcher(fsDir);
 Query query = QueryParser.parse(q, "contents", new StandardAnalyzer());
 Hits hits = is.search(query);
 System.out.println("Found " + hits.length() +
                   " document(s) that matched query '" + q + "':");
 for (int i = 0; i < hits.length(); i++) {
 Document doc = hits.doc(i);
 System.out.println(doc.get("filename"));
 }
}

Выражения, передаваемые QueryParser , анализируются в соответствии с простой грамматикой. Когда встречается недопустимое выражение, QueryParser ParseException .

2,3. Синтаксис выражения QueryParser

Следующие элементы в этом разделе описывают синтаксис, который поддерживает QueryParser для создания различных типов запросов.

Однократный запрос

Строка запроса только из одного слова преобразуется в базовый TermQuery .

Фразовый запрос

Чтобы найти группу слов вместе в поле, заключите слова в двойные кавычки. Запрос «hello world» соответствует точному совпадению фразы, требуя, чтобы «hello» и «world» были последовательными терминами для совпадения. Lucene также поддерживает небрежные фразы, когда термины между кавычками не обязательно должны быть в точном порядке. Коэффициент наклона измеряет количество ходов, необходимых для перестановки членов в точный порядок. Если количество ходов меньше указанного коэффициента наклона, это совпадение. QueryParser анализирует выражение «hello world» ~ 2 как PhraseQuery с коэффициентом PhraseQuery 2, что позволяет сопоставлять фразы «world hello», «hello world», «hello * world» и «hello * * world», где звездочки обозначают неуместные слова в индексе. Обратите внимание, что «world * hello» не совпадает с коэффициентом наклона 2. Поскольку число ходов, чтобы вернуть его в «hello world», равно 3. Прыжок слова «world» в положение звездочки равен единице, « Привет »позиция два, и третий прыжок делает точное совпадение.

Диапазон запроса

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

ЗАМЕЧАНИЯ. В запросах, не относящихся к диапазону дат, используются начальный и конечный термины, введенные пользователем без изменений. В случае {Aardvark TO Zebra} термины не в нижнем регистре. Термины начала и конца не должны содержать пробелов, иначе синтаксический анализ не удастся; разрешены только отдельные слова. Анализатор не запускается в начальные и конечные сроки.

Обработка диапазона дат

Когда встречается запрос диапазона (такой как [1/1/03 TO 12/31/03]), код синтаксического анализатора сначала пытается преобразовать начальный и конечный термины в даты. Если термины являются действительными датами, в соответствии с DateFormat.SHORT и мягким синтаксическим DateFormat.SHORT , тогда даты преобразуются в их внутреннее текстовое представление (однако, индексация поля даты выходит за рамки данной статьи). Если какой-либо из двух терминов не может быть проанализирован как действительная дата, они оба используются как есть для текстового диапазона.

Подстановочные и префиксные запросы

Если термин содержит звездочку или вопросительный знак, он считается WildcardQuery , за исключением случаев, когда термин содержит только QueryParser звездочку и QueryParser оптимизирует его до PrefixQuery . Хотя сам по себе WildcardQuery API поддерживает ведущий подстановочный знак, QueryParser не допускает этого. Примером подстановочного запроса является w * ldc? Rd , тогда как префикс * запроса оптимизируется как PrefixQuery .

Нечеткий запрос

FuzzyQuery Lucene соответствует условиям, близким к указанному. Алгоритм расстояния Левенштейна определяет, насколько близки слагаемые в индексе к заданному целевому слагаемому. «Редактировать расстояние» — это еще один термин для «расстояния Левенштейна» и является мерой сходства между двумя строками, где расстояние измеряется как количество удалений, вставок или замен символов, необходимых для преобразования одной строки в другую. Например, расстояние редактирования между «тремя» и «деревом» равно единице, поскольку требуется удаление только одного символа. Число ходов используется в расчете порога, который является отношением расстояния к длине струны. QueryParser поддерживает нечеткие запросы, используя QueryParser тильду для термина. Например, при поиске wuzza ~ будут найдены документы, содержащие «fuzzy» и «wuzzy». Расстояние редактирования влияет на оценку, так что меньшие расстояния редактирования дают больший балл.

Логический запрос

Текстовое построение логических запросов выполняется с использованием операторов AND, OR и NOT. Термины, перечисленные без указания оператора, используют неявный оператор, который по умолчанию равен OR. Запрос abc xyz будет интерпретирован как abc ИЛИ xyz. Размещение NOT перед термином исключает документы, содержащие следующий термин. Отрицательный термин должен быть объединен по крайней мере с одним неотрицательным сроком, чтобы возвратить документы. Каждый из операторов слов в верхнем регистре имеет сокращенный синтаксис, показанный в следующей таблице.

а или ба ба а не б + а -б

Подробный синтаксис Синтаксис ярлыков
А И Б + а + б

Таблица 1

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

3. Создать индекс с поиском по индексу

В общем случае приложения обычно должны вызывать только унаследованные

1
Searcher.search(org.apache.lucene.search.Query,int)

или же

1
Searcher.search(org.apache.lucene.search.Query,org.apache.lucene.search.Filter,int)

методы. Для повышения производительности мы можем открыть indexSearcher и использовать его для всех других поисковых операций. Вот простой пример того, как создать индекс в lucene и выполнить поиск по этому индексу, используя indexSearcher .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public void simpleLucene()
 
{
 
    Analyzer analyzer = new StandardAnalyzer();
 
 
 
    // Store the index in memory:
 
    Directory directory = new RAMDirectory();
 
 
 
    // To store an index on disk, use this instead (note that the
 
    // parameter true will overwrite the index in that directory
 
    // if one exists):
 
    // Directory directory = FSDirectory.getDirectory("/tmp/myfiles", true);
 
 
 
    IndexWriter iwriter = new IndexWriter(directory, analyzer, true);
 
    iwriter.setMaxFieldLength(25000);
 
 
 
    Document doc = new Document();
 
    String text = "This is the text to be indexed.";
 
    doc.add(new Field("fieldname", text, Field.Store.YES,
 
        Field.Index.TOKENIZED));
 
    iwriter.addDocument(doc);
 
    iwriter.close();
 
     
 
    // Now search the index:
 
    IndexSearcher isearcher = new IndexSearcher(directory);
 
 
 
    // Parse a simple query that searches for "text":
 
    QueryParser parser = new QueryParser("fieldname", analyzer);
 
    Query query = parser.parse("text");
 
    Hits hits = isearcher.search(query);
 
    assertEquals(1, hits.length());
 
 
 
    // Iterate through the results:
 
    for (int i = 0; i < hits.length(); i++)
 
    {
 
      Document hitDoc = hits.doc(i);
 
      assertEquals("This is the text to be indexed.", hitDoc.get("fieldname"));
 
    }
 
 
 
    isearcher.close();
 
    directory.close();
 
}

4. Различные типы запросов

Lucene поддерживает различные запросы. Вот некоторые из них.

  1. TermQuery
  2. BooleanQuery
  3. WildcardQuery
  4. PhraseQuery
  5. PrefixQuery
  6. MultiPhraseQuery
  7. FuzzyQuery
  8. RegexpQuery
  9. TermRangeQuery
  10. NumericRangeQuery
  11. ConstantScoreQuery
  12. DisjunctionMaxQuery
  13. MatchAllDocsQuery

4.1 TermQuery

Соответствует документам с полями, содержащими термин (не проанализирован). Термин запрос отображается в Lucene TermQuery . Следующее соответствует документам, где поле пользователя содержит термин kimchy :

1
2
3
{
 "term" : { "user" : "kimchy" }
}

Повышение также может быть связано с запросом:

1
2
3
{
 "term" : { "user" : { "value" : "kimchy", "boost" : 2.0 } }
}

Или же :

1
2
3
{
 "term" : { "user" : { "term" : "kimchy", "boost" : 2.0 } }
}

В Lucene можно искать определенное слово, которое было проиндексировано, с TermQuery класса TermQuery . В этом руководстве будут сравниваться запросы TermQuery поисками QueryParser , а также показываться некоторые нюансы, связанные с запросом термина.

4.2 BooleanQuery

Мы можем запускать поиск в нескольких полях в Lucene, используя либо API-интерфейс BooleanQuery либо используя MultiFieldQueryParser для анализа текста запроса. Например, если индекс имеет 2 поля FirstName и LastName и если вам нужно найти «John» в поле FirstName и «Travis» в поле LastName можно использовать BooleanQuery как таковой:

1
2
3
4
5
6
7
BooleanQuery bq = new BooleanQuery();
Query qf = new TermQuery(new Lucene.Net.Index.Term("FirstName", "John"));
Query ql = new TermQuery(new Lucene.Net.Index.Term("LastName", "Travis"));
bq.Add(qf, BooleanClause.Occur.MUST);
bq.Add(ql, BooleanClause.Occur.MUST);
IndexSearcher srchr = new IndexSearcher(@"C:\\indexDir");
srchr.Search(bq);

4.3 WildcardQuery

Соответствует документам, поля которых соответствуют шаблону (не анализируются). Поддерживаются подстановочные знаки *, которые соответствуют любой последовательности символов (включая пустую), и?, Которые соответствуют любому отдельному символу. Обратите внимание, что этот запрос может быть медленным, поскольку он должен повторяться по многим терминам. Чтобы предотвратить чрезвычайно медленные запросы с подстановочными знаками, термин с подстановочными знаками не должен начинаться с одного из символов подстановки * или?. Запрос с подстановочными знаками сопоставляется с Lucene WildcardQuery.

1
2
3
{
    "wildcard" : { "user" : "ki*y" }
}

Повышение также может быть связано с запросом:

1
2
3
{
    "wildcard" : { "user" : { "value" : "ki*y", "boost" : 2.0 } }
}

Или же :

1
2
3
{
    "wildcard" : { "user" : { "wildcard" : "ki*y", "boost" : 2.0 } }
}

Этот многоточечный запрос позволяет контролировать, как он переписывается с помощью параметра rewrite.

4.4 PhraseQuery

В Lucene PhaseQuery можно использовать для запроса последовательности терминов, где термины не обязательно должны быть рядом или по порядку. PhaseQuery setSlop() объекта setSlop() можно использовать для установки количества слов между различными словами в фразе запроса.

Мы можем использовать PhraseQuery как это,

1
2
3
4
5
6
Term term1 = new Term(FIELD_CONTENTS, string1);
Term term2 = new Term(FIELD_CONTENTS, string2);
PhraseQuery phraseQuery = new PhraseQuery();
phraseQuery.add(term1);
phraseQuery.add(term2);
phraseQuery.setSlop(slop);

4.5 PrefixQuery

Соответствует документам, имеющим поля, содержащие термины с указанным префиксом (не анализируется). Запрос префикса отображается на Lucene PrefixQuery . Следующее соответствует документам, где поле пользователя содержит термин, начинающийся с ki :

1
2
3
{
    "prefix" : { "user" : "ki" }
}

Повышение также может быть связано с запросом:

1
2
3
{
    "prefix" : { "user" :  { "value" : "ki", "boost" : 2.0 } }
}

Или же :

1
2
3
{
    "prefix" : { "user" :  { "prefix" : "ki", "boost" : 2.0 } }
}

Этот многоточечный запрос позволяет контролировать, как он переписывается с помощью параметра rewrite.

4.6 MultiPhraseQuery

Встроенный MultiPhraseQuery — это определенно нишевый запрос, но он потенциально полезен. MultiPhraseQuery похож на PhraseQuery за исключением того, что он допускает несколько терминов на позицию. Вы можете достичь того же логического эффекта, хотя и с высокой производительностью, перечислив все возможные комбинации фраз и используя BooleanQuery для «ИЛИ» их вместе.

Например, предположим, что мы хотим найти все документы о быстрых лисах, с быстрым или быстрым, за которым следует лиса. Один из подходов состоит в том, чтобы выполнить запрос «Быстрая лиса» ИЛИ «Быстрая лиса». Другой вариант — использовать MultiPhraseQuery .

4.7 FuzzyQuery

FuzzyQuery можно разделить на две категории, а. нечеткий как этот запрос & b. нечеткое, как это поле querya. Нечеткий подобный этому запросу — Нечеткий подобный этому запросу находит документы, которые «похожи» на предоставленный текст, запуская его в одном или нескольких полях.

1
2
3
4
5
6
7
{
    "fuzzy_like_this" : {
        "fields" : ["name.first", "name.last"],
        "like_text" : "text like this one",
        "max_query_terms" : 12
    }
}

fuzzy_like_this можно сократить до flt.
Параметры верхнего уровня fuzzy_like_this включают в себя:

  • fields -> Список полей для запуска, более похожих на этот запрос. По умолчанию используется поле _all.
  • like_text -> Текст для поиска документов, как это, обязательно.
  • ignore_tf -> Следует ли игнорировать термин «частота». По умолчанию false.
  • max_query_terms -> Максимальное количество условий запроса, которые будут включены в любой сгенерированный запрос. По умолчанию 25.
  • fuzziness -> минимальное сходство вариантов вариантов. По умолчанию 0,5. Смотрите раздел под названием «Fuzzinessedit».
  • prefix_length -> Длина обязательного общего префикса для вариантов вариантов. По умолчанию 0.
  • boost -> Устанавливает значение повышения запроса. По умолчанию 1.0.
  • analyzer -> Анализатор, который будет использоваться для анализа текста. По умолчанию используется анализатор, связанный с полем.

Размывает ВСЕ термины, представленные в виде строк, а затем выбирает лучшие n дифференцирующих терминов. По сути это смешивает поведение FuzzyQuery и MoreLikeThis но с особым учетом нечетких скоринговых факторов. Как правило, это приводит к хорошим результатам для запросов, в которых пользователи могут предоставлять подробности по ряду полей и не знать синтаксиса логических запросов, а также хотят иметь степень нечеткого соответствия и быстрый запрос.

Для каждого исходного термина нечеткие варианты хранятся в BooleanQuery без координатного фактора (потому что мы не ищем совпадений для нескольких вариантов в одном документе). Кроме того, специализированный TermQuery используется для вариантов и не использует IDF этого варианта термина, потому что это предпочло бы более редкие термины, такие как орфографические ошибки. Вместо этого все варианты используют один и тот же рейтинг IDF (тот, который используется для термина исходного запроса), и это учитывается при повышении варианта. Если термин исходного запроса не существует в индексе, используется средняя IDF вариантов. нечеткое, как это поле запроса–

Запрос fuzzy_like_this_field такой же, как запрос fuzzy_like_this , за исключением того, что он выполняется для одного поля. Он обеспечивает более качественный DSL-запрос по сравнению с общим запросом fuzzy_like_this и поддерживает запрос типизированных полей (автоматически переносит типизированные поля с типом filter, чтобы они соответствовали только определенному типу).

1
2
3
4
5
6
7
8
{
    "fuzzy_like_this_field" : {
        "name.first" : {
            "like_text" : "text like this one",
            "max_query_terms" : 12
        }
    }
}

Поле fuzzy_like_this_field может быть сокращено до flt_field. Параметры верхнего уровня fuzzy_like_this_field включают в себя:

  • like_text -> Текст для поиска документов, как это, обязательно.
  • ignore_tf -> Следует ли игнорировать термин «частота». По умолчанию false.
  • max_query_terms -> Максимальное количество условий запроса, которые будут включены в любой сгенерированный запрос. По умолчанию 25.
  • нечеткость -> нечеткость вариантов вариантов. По умолчанию 0,5. Смотрите раздел под названием «Fuzzinessedit».
  • prefix_length -> Длина обязательного общего префикса для вариантов вариантов. По умолчанию 0.
  • boost -> Устанавливает значение повышения запроса. По умолчанию 1.0.
  • анализатор -> Анализатор, который будет использоваться для анализа текста. По умолчанию используется анализатор, связанный с полем.

4.8 RegexpQuery

Запрос регулярного выражения позволяет вам использовать запросы с регулярными выражениями. См. Синтаксис регулярных выражений для получения подробной информации о поддерживаемом языке регулярных выражений.

Примечание. Производительность запроса регулярного выражения в значительной степени зависит от выбранного регулярного выражения. Совпадение всего, как. * Очень медленное, а также использование регулярных выражений. Если возможно, вы должны попытаться использовать длинный префикс, прежде чем ваше регулярное выражение начинается. Подстановочные знаки, такие как . *? + , В основном снижают производительность.

1
2
3
4
5
{
    "regexp":{
        "name.first": "s.*y"
    }
}

Повышение также поддерживается

1
2
3
4
5
6
7
8
{
    "regexp":{
        "name.first":{
            "value":"s.*y",
            "boost":1.2
        }
    }
}

Вы также можете использовать специальные флаги

1
2
3
4
5
6
7
8
{
    "regexp":{
        "name.first": {
            "value": "s.*y",
            "flags" : "INTERSECTION|COMPLEMENT|EMPTY"
        }
    }
}

Возможные флаги: ALL , ANYSTRING , ANYSTRING , ANYSTRING , EMPTY , INTERSECTION , INTERVAL или NONE . Запросы регулярных выражений поддерживаются запросами regexp и query_string . Механизм регулярных выражений Lucene не является Perl-совместимым, но поддерживает меньший диапазон операторов.

Стандартные операторы

Привязка Большинство механизмов регулярных выражений позволяют вам сопоставить любую часть строки. Если вы хотите, чтобы шаблон регулярного выражения начинался в начале строки или заканчивался в конце строки, то вам нужно специально привязать его, используя ^, чтобы указать начало, или $, чтобы указать конец. Шаблоны Lucene всегда привязываются. Указанный шаблон должен соответствовать всей строке. Для строки «abcde» :

1
ab.* # match
1
abcd # no match

Разрешенные персонажи

Любые символы Юникода могут использоваться в шаблоне, но некоторые символы зарезервированы и должны быть экранированы. Стандартные зарезервированные символы:

, ? + * | {} [] () ”\

Если вы включите дополнительные функции (см. Ниже), то эти символы также могут быть зарезервированы:

# @ & <> ~

Любой зарезервированный символ может быть экранирован обратной косой чертой «\ *», включая буквенный символ обратной косой черты:

«\\»

Кроме того, любые символы (кроме двойных кавычек) интерпретируются буквально, когда они заключены в двойные кавычки:

джон»@ smith.com»

Подходим любой персонаж

Период «.» может использоваться для представления любого символа. Для строки «abcde»:

1
ab... # match
1
a.c.e # match

Один или больше

Знак «+» можно использовать для повторения предыдущего кратчайшего шаблона один или несколько раз. Для строки «aaabbb»:

1
a+b+ # match
1
aa+bb+ # match
1
a+.+ # match
1
aa+bbb+ # no match

Ноль или более-

Звездочку «*» можно использовать для совпадения с предыдущим кратчайшим шаблоном ноль или более раз. Для строки «aaabbb»:

1
a*b* # match
1
a*b*c* # match
1
.*bbb.* # match
1
aaa*bbb* # match

Ноль или один

Вопросительный знак «?» делает предыдущий кратчайший образец необязательным. Это соответствует нулю или один раз. Для строки «aaabbb»:

1
aaa?bbb? # match
1
aaaa?bbbb? # match
1
.....?.? # match
1
aa?bb? # no match

Min-к-макс

С помощью фигурных скобок «{}» можно указать минимальное и (необязательно) максимальное количество повторений предыдущего кратчайшего шаблона. Разрешенные формы:

1
{5} # repeat exactly 5 times
1
{2,5} # repeat at least twice and at most 5 times
1
{2,} # repeat at least twice

Для строки «aaabbb»:

1
a{3}b{3} # match
1
a{2,4}b{2,4} # match
1
a{2,}b{2,} # match
1
.{3}.{3} # match
1
a{4}b{4} # no match
1
a{4,6}b{4,6} # no match
1
a{4,}b{4,} # no match

Группировка

Скобки «()» могут быть использованы для формирования подшаблонов. Перечисленные выше количественные операторы работают с кратчайшим предыдущим шаблоном, который может быть группой. Для строки «ababab»:

1
(ab)+ # match
1
ab(ab)+ # match
1
(..)+ # match
1
(...)+ # no match
1
(ab)* # match
1
abab(ab)? # match
1
ab(ab)? # no match
1
(ab){3} # match
1
(ab){1,2} # no match

перемежаемость

Символ трубы «|» действует как оператор ИЛИ. Совпадение будет успешным, если шаблон с левой стороны ИЛИ с правой стороны совпадает. Чередование применяется к самому длинному шаблону, а не к самому короткому. Для строки «aabb»:

1
aabb|bbaa # match
1
aacc|bb # no match aa(cc|bb) # match
1
a+|b+ # no match
1
a+b+|b+a+ # match
1
a+(b|c)+ # match

Классы персонажей

Диапазоны потенциальных символов могут быть представлены как классы символов, заключив их в квадратные скобки «[]». Ведущий ^ отрицает класс персонажа. Разрешенные формы:

1
[abc] # 'a' or 'b' or 'c'
1
[a-c] # 'a' or 'b' or 'c'
1
[-abc] # '-' or 'a' or 'b' or 'c'
1
[abc\\-] # '-' or 'a' or 'b' or 'c'
1
[^a-c] # any character except 'a' or 'b' or 'c'
1
[^a-c] # any character except 'a' or 'b' or 'c'
1
[-abc] # '-' or 'a' or 'b' or 'c'
1
[abc\\-] # '-' or 'a' or 'b' or 'c'

Обратите внимание, что тире «-» указывает диапазон символов, если это не первый символ или если он не экранирован обратной косой чертой. Для строки «abcd»:

1
ab[cd]+ # match
1
[a-d]+ # match
1
[^a-d]+ # no match

4.9 TermRangeQuery

Query который соответствует документам в пределах диапазона условий. Этот запрос сопоставляет документы, ищущие термины, попадающие в указанный диапазон, в соответствии с String#compareTo(String) , если не Collator . Он не предназначен для числовых диапазонов.

Вот пример того, как использовать TermRangeQuery в Lucene,

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
private Query createQuery(String field, DateOperator dop) throws UnsupportedSearchException {
Date date = dop.getDate();
DateResolution res = dop.getDateResultion();
DateTools.Resolution dRes = toResolution(res);
String value = DateTools.dateToString(date, dRes);
switch(dop.getType()) {
    case ON:
        return new TermQuery(new Term(field ,value));
    case BEFORE:
        return new TermRangeQuery(field, DateTools.dateToString(MIN_DATE, dRes), value, true, false);
    case AFTER:
        return new TermRangeQuery(field, value, DateTools.dateToString(MAX_DATE, dRes), false, true);
    default:
        throw new UnsupportedSearchException();
    }
}

4.10 NumericRangeQuery

NumericRangeQuery , который соответствует числовым значениям в указанном диапазоне. Чтобы использовать это, вы должны сначала проиндексировать числовые значения. Мы можем объединить NumericRangeQuery с TermQuery следующим образом:

1
2
3
4
String termQueryString = "title:\\"hello world\\"";
Query termQuery = parser.parse(termQueryString);
Query pageQueryRange = NumericRangeQuery.newIntRange("page_count", 10, 20, true, true);
Query query = termQuery.combine(new Query[]{termQuery, pageQueryRange});

4.11 ConstantScoreQuery

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

1
2
3
4
5
6
7
8
{
    "constant_score" : {
        "filter" : {
            "term" : { "user" : "kimchy"}
        },
        "boost" : 1.2
    }
}

Объект фильтра может содержать только элементы фильтра, но не запросы. Фильтры могут быть намного быстрее по сравнению с запросами, поскольку они не выполняют никакой оценки, особенно когда они кэшируются. Запрос также может быть включен в запрос constant_score:

1
2
3
4
5
6
7
8
{
    "constant_score" : {
        "query" : {
            "term" : { "user" : "kimchy"}
        },
        "boost" : 1.2
    }
}

4.12 DisjunctionMaxQuery

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

Это полезно при поиске слова в нескольких полях с разными коэффициентами усиления (чтобы поля не могли быть эквивалентно объединены в одно поле поиска). Мы хотим, чтобы основной счет был тот, который связан с наибольшим усилением, а не сумма баллов по полю (как даст булев запрос). Если запрос «слон-альбинос», это гарантирует, что «альбинос», соответствующий одному полю, и «слон», соответствующий другому, получат более высокий балл, чем «альбинос», соответствующий обоим полям. Чтобы получить этот результат, используйте как Boolean Query, так и DisjunctionMaxQuery : для каждого термина DisjunctionMaxQuery ищет его в каждом поле, в то время как набор этих DisjunctionMaxQuery объединяется в BooleanQuery .

Возможность прерывания связей позволяет оценивать результаты, включающие один и тот же термин в нескольких полях, лучше, чем результаты, включающие этот термин только в лучшее из этих нескольких полей, не путая это с лучшим случаем двух разных терминов в нескольких полях. по умолчанию tie_breaker — 0.0. Этот запрос сопоставляется с Lucene DisjunctionMaxQuery .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
{
    "dis_max" : {
        "tie_breaker" : 0.7,
        "boost" : 1.2,
        "queries" : [
            {
                "term" : { "age" : 34 }
            },
            {
                "term" : { "age" : 35 }
            }
        ]
    }
}

4.13 MatchAllDocsQuery

Запрос, который соответствует всем документам. Карты для Lucene MatchAllDocsQuery .

1
2
3
{
    "match_all" : { }
}

Который также может иметь повышение, связанное с этим:

1
2
3
{
    "match_all" : { "boost" : 1.2 }
}