2015-04-21 3 views
10

Моя схема:Solr: поиск с различными комбинациями пространства, дефис, обсадных и пунктуацией

<fieldType name="text" class="solr.TextField" positionIncrementGap="100"> 
    <analyzer> 
    <tokenizer class="solr.WhitespaceTokenizerFactory"/> 
    <filter class="solr.StopFilterFactory" 
      ignoreCase="true" 
      words="stopwords.txt" 
      enablePositionIncrements="true" 
      /> 
    <filter class="solr.WordDelimiterFilterFactory" 
      generateWordParts="1" generateNumberParts="1" 
      catenateWords="1" catenateNumbers="1" catenateAll="0" 
      splitOnCaseChange="1" splitOnNumerics="0"/> 
    <filter class="solr.LowerCaseFilterFactory"/> 
    <filter class="solr.SnowballPorterFilterFactory" language="English" 
      protected="protwords.txt"/> 
    </analyzer> 
</fieldType> 

Комбинации, которые я хочу работать:

"Walmart", "WalMart", «Wal Mart "," Wal-Mart "," Wal-mart "

Учитывая любую из этих строк, я хочу найти другую.

Таким образом, существует 25 таких комбинаций, как указано ниже:

(Первая колонка обозначает входной текст для поиска, второй столбец обозначает ожидается матч)

(Walmart,Walmart) 
(Walmart,WalMart) 
(Walmart,Wal Mart) 
(Walmart,Wal-Mart) 
(Walmart,Wal-mart) 
(WalMart,Walmart) 
(WalMart,WalMart) 
(WalMart,Wal Mart) 
(WalMart,Wal-Mart) 
(WalMart,Wal-mart) 
(Wal Mart,Walmart) 
(Wal Mart,WalMart) 
(Wal Mart,Wal Mart) 
(Wal Mart,Wal-Mart) 
(Wal Mart,Wal-mart) 
(Wal-Mart,Walmart) 
(Wal-Mart,WalMart) 
(Wal-Mart,Wal Mart) 
(Wal-Mart,Wal-Mart) 
(Wal-Mart,Wal-mart) 
(Wal-mart,Walmart) 
(Wal-mart,WalMart) 
(Wal-mart,Wal Mart) 
(Wal-mart,Wal-Mart) 
(Wal-mart,Wal-mart) 

Текущие ограничения с моей схемой:

1. "Wal-Mart" -> "Walmart", 
2. "Wal Mart" -> "Walmart", 
3. "Walmart" -> "Wal Mart", 
4. "Wal-mart" -> "Walmart", 
5. "WalMart" -> "Walmart" 

Скриншот анализатора:

Analyzer screenshot using initial schema

Я пробовал различные комбинации фильтров пытаются решить эти ограничения, так что я получил споткнулся решением при условии, по адресу: Solr - case-insensitive search do not work

Хотя, кажется, преодолеть одно из ограничений, которые у меня есть (см # 5 WalMart - > Walmart), это в целом хуже, чем у меня раньше. Сейчас он не работает в тех случаях, как:

(Wal Mart,WalMart), 
(Wal-Mart,WalMart), 
(Wal-mart,WalMart), 
(WalMart,Wal Mart) 
besides cases 1 to 4 as mentioned above 

Analyzer после изменения схемы: enter image description here

Вопросы:

  1. Почему "WalMart" не соответствует "Walmart" с моей первоначальной схеме ? Анализатор Solr наглядно показывает мне, что во время индексации было произведено 3 жетона:, mart, walmart. В течение времени запроса: он выдал 1 токен: walmart (пока неясно, почему он будет производить только 1 токен), я не понимаю, почему он не соответствует, так как walmart содержится в токенах запроса и индекса.

  2. Проблема, о которой я упоминал здесь, - это всего лишь один случай использования. Есть еще несколько сложных из них, как:

    Слова с апострофа: "Mc Donalds", "Макдональдс", "Mc Donalds", "Макдональдс",

    Слова "Макдональдс", "Макдоналдс" с различными пунктуациями: «Mc-Donald Engineering Company, Inc.»

В общем, что это лучший способ, чтобы обойти моделирования схемы с такого рода требования? NGrams? Укажите одинаковые данные в разных полях (в разных форматах) и используйте директиву copyField (https://wiki.apache.org/solr/SchemaXml#Indexing_same_data_in_multiple_fields)? Каковы последствия этого?

EDIT: Оператор по умолчанию в моей схеме Solr имеет значение AND. Я не могу изменить его на OR.

ответ

2

Обновление версии Lucene (4.4 до 4.10) в solrconfig.xml исправили проблему волшебно! У меня больше нет ограничений, и мой анализатор запросов ведет себя так же, как ожидалось.

+0

Переход с 4.4 до 4.10 - это обновление ... :) – cheffe

+0

@cheffe thats weird .. Я думал, что 4.4 больше, чем 4.10 :) –

4

Мы рассмотрели переносимые слова как частный случай и написали пользовательский анализатор, который использовался во время индекса, чтобы создать три версии этого токена, поэтому в вашем случае wal-mart станет walmart, wal mart и wal-mart. Каждый из этих синонимов был написан с использованием специального SynonymFilter, который был первоначально адаптирован из примера в книге Lucene in Action. Синонимичный фильтр сидел между токенизатором Whitespace и нижним токенизатором.

В момент поиска любая из трех версий будет соответствовать одному из синонимов индекса.

+0

Спасибо, что нашли время, чтобы ответить. SynonymFilters будут работать, если бы у меня был хороший набор данных синонимов, что, к сожалению, неверно в моем случае. –

+1

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

+0

дефис - это всего лишь один сценарий нескольких. Существуют и другие виды пунктуации. Я боюсь, что мы могли бы даже масштабироваться с такими особыми случаями :) –

2

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

<tokenizer class="solr.WhitespaceTokenizerFactory"/> 
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1" splitOnNumerics="0"/> 
<filter class="solr.LowerCaseFilterFactory"/> 
<filter class="solr.StopFilterFactory" 
     words="stopwords.txt" 
     enablePositionIncrements="true" 
     /> 
<filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/> 

В целом, это не слишком далеко. Главная проблема - «Wal Mart» и «Walmart». Для каждого из них WordDelimiterFilter не имеет к этому никакого отношения, это токенизатор, который расщепляется здесь. «Wal Mart» разделяется токенизатором. «Walmart» никогда не разделяется, так как ничто не может разумно знать, где его нужно разделить.

Одно из решений, что было бы использовать вместо KeywordTokenizer, и пусть WordDelimiterFilter делать все из tokenizing, но это будет вести к другим проблемам (в частности, при работе с более длинным, сложным текстом, как ваш «Mc -Donald Engineering Company, Inc. "пример будет проблематичным).

Вместо этого я бы рекомендовал ShingleFilter. Это позволяет объединить соседние маркеры в один токен для поиска. Это означает, что при индексировании «Wal Mart» он будет принимать токены «wal» и «mart», а также индексировать термин «walmart». Обычно он также вставляет разделитель, но для этого случая вы захотите переопределить это поведение и указать разделитель "".

Мы поместим ShingleFilter в конце сейчас (это будет, как правило, завинтить, вытекающие если вы поставите его перед стеммер):

<tokenizer class="solr.WhitespaceTokenizerFactory"/> 
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1" splitOnNumerics="0"/> 
<filter class="solr.LowerCaseFilterFactory"/> 
<filter class="solr.StopFilterFactory" 
     words="stopwords.txt" 
     enablePositionIncrements="true" 
     /> 
<filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/> 
<filter class="solr.ShingleFilterFactory" maxShingleSize="2" tokenSeparator=""/> 

Это будет только создавать черепицу из 2 последовательных лексем (как а также оригинальные одиночные токены), поэтому я предполагаю, что вам не нужно больше сочетаться (если вам понадобится «дореми», например, «Do Re Mi»). Но для приведенных примеров это работает в моих тестах.

+0

Хотя это устраняет ограничение на случай «Walmart' ->« Wal Mart », это хуже, поскольку эти три случая, которые проходят раньше, терпят неудачу:« Wal-Mart -> Wal Mart »,« Wal-mart -> Wal Mart » , 'WalMart -> Wal Mart'. Также для другого варианта использования McDonald's эти случаи также потерпят неудачу: «McDonald's -> Mc Donald's',« McDonald's »-> Mc Donalds',« McDonald's »-> Mc Donald's',« McDonald's's »-> Mc donalds' –

+0

. вы переиндексации после внесения изменений в анализатор? – femtoRgon

+0

Я начал с чистого листа, перезапустил Solr и повторил мои тесты (которые делают индексацию с последующим запросом). –

4

Почему «WalMart» не соответствует «Walmart» с моей начальной схемой?

Потому что вы определили параметр mm вашего обработчика DisMax/eDismax со слишком высоким значением. Я играл с ним. Когда вы определяете значение mm до 100%, вы не получите соответствия. Но почему?

Поскольку вы используете тот же анализатор для запроса и времени индекса. Ваш поисковый термин «WalMart» разделен на 3 жетона (слова). А именно это «wal», «mart» и «walmart». Теперь Solr обрабатывает каждое слово индивидуально, если рассчитывать на <str name="mm">100%</str> *.

Кстати я воспроизводимой вашу проблему, но проблема возникает при индексировании Walmart, но запрашивая с WalMart. При выполнении этого наоборот, он работает нормально.

Вы можете переопределить это с помощью LocalParams, вы можете перефразировать свой запрос следующим образом: {!mm=1}WalMart.

Есть несколько более сложных, таких как [...] «Мак Дональд» [в соответствии] Слова с различными пунктуациями: «Mc-Donald Engineering Company, Inc.»

Здесь также играет параметр mm.

В целом, что лучше всего подходит для моделирования схемы с таким требованием?

Здесь я согласен с Sujit Pal, вы должны пойти и реализовать собственную копию SynonymFilter. Зачем? Потому что он работает иначе, чем другие фильтры и токенизаторы. Он создает токены вместо смещения индексированных слов.

В чем дело? Он не увеличит количество токенов вашего запроса. И вы можете выполнить обратную перенос (объединение двух слов, разделенных пробелом).

Но нам не хватает хорошего файла synonyms.txt и он не может поддерживать его в актуальном состоянии.

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

Обновление Я думаю, вы также можете попробовать PatternCaptureGroupTokenFilter, но решение названия компаний с регулярными выражениями может скоро столкнуться с его «пределами». Я расскажу об этом позже.


* Вы можете найти это в solrconfig.xml, посмотрите на ваши <requestHandler ... />

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