Solr Dismax handler - пробелы и поведение специальных символов - PullRequest
0 голосов
/ 25 октября 2011

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

Вот мой запрос:

q=histoire-france&start=0&rows=10&sort=score+desc&defType=dismax&qf=any^1.0&mm=100%

Разобранный запрос:

<str name="parsedquery_toString">+((any:histoir any:franc)) ()</str>

У меня 17000 результатов, потому что Solr выполняет ИЛИ (должно быть И).

У меня нет проблем, когда я использую пробел вместо специального символа:

q=histoire france&start=0&rows=10&sort=score+desc&defType=dismax&qf=any^1.0&mm=100%

<str name="parsedquery_toString">+(((any:histoir) (any:franc))~2) ()</str>

2000 результатов по этому запросу.

Вот мой schema.xml (соответствующие части):

<fieldType name="text" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="false">
      <analyzer type="index">
        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1" preserveOriginal="1"/>
        <filter class="solr.LowerCaseFilterFactory"/>
        <filter class="solr.CommonGramsFilterFactory" words="stopwords_french.txt" ignoreCase="true"/>
        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords_french.txt" enablePositionIncrements="true"/>
        <filter class="solr.SnowballPorterFilterFactory" language="French" protected="protwords.txt"/>
        <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
        <filter class="solr.ASCIIFoldingFilterFactory"/>
      </analyzer>
      <analyzer type="query">
        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
        <!--<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>-->
        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1" preserveOriginal="0"/>
        <filter class="solr.LowerCaseFilterFactory"/>
        <filter class="solr.CommonGramsFilterFactory" words="stopwords_french.txt" ignoreCase="true"/>
        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords_french.txt" enablePositionIncrements="true"/>
        <filter class="solr.SnowballPorterFilterFactory" language="French" protected="protwords.txt"/>
        <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
        <filter class="solr.ASCIIFoldingFilterFactory"/>
      </analyzer>
    </fieldType>

Я даже пытался использовать PatternTokenizerFactory для токенизации на пробелах и специальных символах, но без изменений ...

Мой текущий обходной путь - заменить все специальные символы пробелами перед отправкой запроса в Solr, но это не удовлетворяет.

РЕДАКТИРОВАТЬ: Даже с charFilter (PatternReplaceCharFilterFactory), чтобы заменить специальные символы пробелами, это не работает ...

Первая строка анализа через solr admin, с подробным выводом, для запроса = 'histoire-france':

org.apache.solr.analysis.PatternReplaceCharFilterFactory {replacement= , pattern=([,;./\\'&-]), luceneMatchVersion=LUCENE_32}
text    histoire france

'-' заменяется на '', затем токенизируется WhitespaceTokenizerFactory. Тем не менее, у меня все еще разные результаты для «histoire-france» и «histoire france».

Я что-то пропустил?

Ответы [ 4 ]

3 голосов
/ 06 февраля 2012

Вы получаете различное количество результатов поиска по «histoire-france» и «histoire france», потому что анализатор запросов создает запрос фразы в первом случае и логический запрос (разделяет два слова) во втором случае.

Это неочевидное поведение imho, но я считаю, что трудно удовлетворить все варианты использования.

Чтобы сделать поиск, трактующий 'histoire-france' как просто два слова, вы можете добавить " solr.PositionFilterFactory "до конца анализатора запросов, например:

  <analyzer type="query">
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.PositionFilterFactory" />
  </analyzer>

Тогда результаты поиска для 'histoire-france' и 'histoire france' будут равны.

Обратите внимание, что фильтр позиции можетбыть нежелательным для поиска по фразе (присутствуют и «исторический», и «французский»).Вместо этого рассмотрите возможность использования параметра проскальзывания запроса qs> 0, если вы изменили последовательность терминов с помощью, скажем, фильтра NGram.

1 голос
/ 24 января 2013

Это была ошибка: https://issues.apache.org/jira/browse/SOLR-3589

Если для edismax mm установлено значение 100%, если один из токенов разделен на два токены цепью анализатора (то есть «пожарная муха» => пожарная муха), мм параметр игнорируется и эквивалент запроса ИЛИ для "огонь ИЛИ летать" производится. Это особенно проблема для языков, которые не используйте пробел для разделения слов, таких как китайский или японский.

Исправлено в Solr 4.1 (22 января 2013 г.)

1 голос
/ 25 октября 2011

используя WhitespaceTokenizerFactory, Solr разделит вашу строку запроса на слова.

Но после токенизации вы (Solr) разделите ваше слово (снова) на термины, используя solr.WordDelimiterFilterFactory .Посмотрите документацию и посмотрите пример Wi-Fi.

Это может быть одной из причин, почему histoire france и histoire-france обрабатываются по-разному.

2-й: не забывайте,что DSIMAX обрабатывает (обычно) запросный термин как «термин», а также (дополнительно) снова как анализируемую строку.

Чтобы решить вашу проблему, вы можете попытаться избежать разделителя мира и попытаться обработать «токенизацию»"с помощью PatternTokenizerFactory (как вы пытались раньше, но теперь без WordDelimiterFilterFactory).

Если это не сработает, попробуйте опубликовать полный вывод файла analysys.jsp

0 голосов
/ 25 октября 2011

Включите для autoGeneratePhraseQueries значение true, и это будет генерировать запросы фраз.
Таким образом, при поиске по histoire-franc он генерирует запрос с кавычками, который включает только документы, содержащие оба слова в качестве сопоставляемой фразы.

<str name="parsedquery">(+DisjunctionMaxQuery(((any:histoire any:franc))))/no_coord</str>

Пример рабочей конфигурации -

<fieldType name="text_test" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
  <analyzer type="index">
    <tokenizer class="solr.WhitespaceTokenizerFactory"/>
    <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.WhitespaceTokenizerFactory"/>
    <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
</fieldType>

Используйте запрос slop, чтобы указать количество отказов, например, qs=10 во фразе запроса.

<str name="parsedquery">(+DisjunctionMaxQuery((any:"histoire france"~10)))/no_coord</str>
...