Запрос Lucene: bla ~* (распознают слова, которые запускаются с чего-то нечеткого), как?

В синтаксисе запроса Lucene я хотел бы объединиться * и ~ в допустимом запросе, подобном: bla ~*//недопустимый запрос

Значение: распознайте слова, которые начинаются с "bla" или чего-то подобного "bla".

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

<fieldtype name="text_ngrams" class="solr.TextField">
  <analyzer type="index">
        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="0"/>
        <filter class="solr.LowerCaseFilterFactory"/>
        <filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="15" side="front"/>
  </analyzer>
  <analyzer type="query">
        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="0"/>
        <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>

В случае, если Вы не используете SOLR, это делает следующее.

Indextime: Индексные данные путем создания поля, содержащего все префиксы моего (короткого) входа.

Searchtime: только используйте ~ оператор, поскольку префиксы явно присутствуют в индексе.

10
задан pnuts 21 November 2015 в 13:15
поделиться

4 ответа

Я не верю, что Lucene поддерживает что-либо подобное, и не Я считаю, что у этого есть тривиальное решение.

«Нечеткий» поиск не работает с фиксированным количеством символов. bla ~ может, например, соответствовать blah , поэтому он должен учитывать весь термин.

Что вы могли бы сделать, так это реализовать алгоритм расширения запроса, который взял бы запрос bla ~ * и преобразовал его в серию запросов ИЛИ

bla* OR blb* OR blc OR .... etc.

Но это действительно возможно только в том случае, если строка очень короткая. или если вы можете сузить расширение на основе некоторых правил.

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

Вы не указываете, зачем вам это нужно, возможно, это вызовет другие решения.

Один из сценариев, который я могу придумать, связан с разными формами слов. Например. обнаружение автомобилей и автомобилей .

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

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

Например. поиск cars переводится в car OR cars .Это было успешно применено для моего языка по крайней мере в одной поисковой системе, но, очевидно, реализовать его нетривиально.

2
ответ дан 4 December 2019 в 01:00
поделиться

Вы имеете в виду, что хотите объединить подстановочный знак и нечеткий запрос? Вы можете использовать логический запрос с условием ИЛИ для объединения, например:

BooleanQuery bq = new BooleanQuery();

Query q1 = //here goes your wildcard query
bq.Add(q1, BooleanClause...)

Query q2 = //here goes your fuzzy query
bq.Add(q2, BooleanClause...)
0
ответ дан 4 December 2019 в 01:00
поделиться

Это для службы поиска адресов, где я хочу предлагать адреса на основе частично набранных и, возможно, неправильно введенных названий улиц/городов/и т.д. (любая комбинация). (представьте ajax, пользователи вводят частичные адреса улиц в текстовое поле)

Для этого случая предложенное расширение запроса, возможно, не так осуществимо, поскольку частичная строка (адрес улицы) может стать длиннее, чем "короткая" :)

Нормализация

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

"miklabraut 42, 101 reykjavík" при нормализации станет "miklabrat 42 101 rekavik".

Итак, построение индекса следующим образом:

1) построить индекс с записями, содержащими "нормализованные" версии названий улиц, городов и т.д., с одним адресом улицы на документ (1 или несколько полей).

И выполните поиск по индексу следующим образом:

2) нормализуйте входные строки (например, mikl reyk), используемые для формирования запросов (например, mik rek). 3) использовать подстановочный знак для выполнения поиска (например, mik* AND rek*), оставив нечеткую часть.

Это будет работать, если алгоритм нормализации достаточно хорош :)

1
ответ дан 4 December 2019 в 01:00
поделиться

в основной ветке разработки lucene (еще не выпуск), есть код для поддержки таких случаев использования, через AutomatonQuery. Предупреждение: API-интерфейсы могут / будут изменены до его выпуска, но это дает вам представление.

Вот пример для вашего случая:

// a term representative of the query, containing the field. 
// the term text is not so important and only used for toString() and such
Term term = new Term("yourfield", "bla~*");

// builds a DFA that accepts all strings within an edit distance of 2 from "bla"
Automaton fuzzy = new LevenshteinAutomata("bla").toAutomaton(2);

// concatenate this DFA with another DFA equivalent to the "*" operator
Automaton fuzzyPrefix = BasicOperations.concatenate(fuzzy, BasicAutomata.makeAnyString());

// build a query, search with it to get results.
AutomatonQuery query = new AutomatonQuery(term, fuzzyPrefix);
8
ответ дан 4 December 2019 в 01:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: