2010-04-13 5 views
10

В синтаксисе запросов Lucene Я хотел бы объединить * и ~ в допустимом запросе аналогичен: ла ~ * // некорректного запросаLucene query: bla ~ * (совпадающие слова, начинающиеся с чего-то нечеткого), как?

Значение: Пожалуйста, сопрягать слова, которые начинаются с «л» или что-то подобное «л».

Update: Что я делаю сейчас, работает небольшой вход, это использовать следующий (фрагмент схемы 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: используйте только оператор ~, поскольку префиксы явно указаны в индексе.

ответ

2

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

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

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

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

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

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

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

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

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

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

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

+0

Althoug нечеткий поиск не работают на фиксированное количество символов, для моего случая просто используя ~ не будет работать (для большого дифференциала в подсчете символов). Я хочу соответствовать, например. Санла в Сундлаугарвегур. –

+0

, конечно, если бы я мог сказать lucene только совпадение по первым символам x каждого слова в индексе, используя ~ будет работать ... –

+0

Вам нужно будет выйти за рамки Lucene здесь, использовать алгоритм сравнения строк, такой как Levenstein, Jaro -Winkler и т. Д. (Qv. Ниже) – Mikos

0

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

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

Я не верю, что это выполнит то, что спрашивает OP, поскольку это в основном станет «bar ~ OR bar *», что не то же самое, что «bar ~ *», и не найдет (например) «brafoo». – Kris

+0

yup, это не то, что я хочу :) –

+0

Хорошо, спасибо за разъяснение, один подход, который я использовал (для сопоставления имен белков и т. Д.) С использованием строковых расстояний, таких как Smith-Waterman, Jaro-Winkler и т. Д. Инструмент вроде SimMetrics может помогите http://www.dcs.shef.ac.uk/~sam/simmetrics.html – Mikos

1

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

В этом случае предлагаемое расширение запрос, возможно, не так возможно, как части строки (почтовый адрес) может стать больше, чем «короткий» :)

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

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

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

Так, индекс здания, как этот:

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

И поиск индекс, как этот:

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

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

7

в багажнике развития 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); 
+0

Я только что вернулся к этому вопросу и снова увидел ваш ответ. Ты это пробовал? То, что я делаю сейчас (работает для небольшого ввода), состоит в том, чтобы сгенерировать все префиксы моего ввода и поместить префиксы в индекс.Тогда мне нужно всего лишь использовать оператор ~ и получить функциональность, например, ~ * –

+0

. Ваше обходное решение прекрасно подходит для небольших входов ... но, как вы намекали, будет проблемой для больших входов: вы добавите огромное количество терминов и проводки для всех этих префиксов ... это сделает нечеткий запрос pre-Lucene 4.0 еще медленнее, поскольку он выполняет линейное сканирование всех терминов. –

+0

Есть ли синтаксис запроса Lucene, который дает вам доступ к запросу Automaton через Solr без кодирования? – wrschneider

 Смежные вопросы

  • Нет связанных вопросов^_^