Фасеты Solr игнорируют стоп-слова во время запроса

Я использую Solr 4.6.0 и пытаюсь сгруппировать наиболее частые термины по годам. Поскольку возможно, что мои игнорируемые слова могут часто меняться, я не применяю стоп-слова во время индексации. Вместо этого во время запроса используются все динамические списки слов, такие как игнорируемые слова, ключевые слова и синонимы. Но хотя список запрещенных слов включает такие термины, как «из» и «the», они все равно отображаются в списке результатов (см. Результаты).

Вопрос: как получить результаты с фасеткой и фильтром по запрещенным словам, если я использую StopFilterFactory только во время запроса?

Дополнительная информация

Если я использую StopFilterFactory во время индексации, все будет так, как ожидалось. Когда я запускаю свой запрос, такие термины, как «из» и «the», отфильтровываются.

Я также протестировал функциональность fieldtype text_en с помощью инструмента анализа администратора Solr, и результаты оказались ожидаемыми - «of» и «the» отфильтрованы. Это означает, что почему-то SearchHandler не вызывает правильный анализатор?

Запрос

http://ip:port/solr/collection1/select?q=*:*&rows=0&facet=true&facet.pivot=year,text

Результаты

[..]
<lst name="facet_pivot">
  <arr name="year,text">
    <lst>
      <str name="field">year</str>
      <int name="value">2009</int>
      <int name="count">139</int>
      <arr name="pivot">
        <lst>
          <str name="field">text</str>
          <str name="value">of</str>
          <int name="count">135</int>
        </lst>
        <lst>
          <str name="field">text</str>
          <str name="value">the</str>
          <int name="count">135</int>
        </lst>
        <lst>
          <str name="field">text</str>
          <str name="value">and</str>
          <int name="count">123</int>
[..]

Schema.xml

<field name="year" type="int" indexed="true" stored="true" />
    <field name="text" type="text_en" indexed="true" stored="true" multiValued="true" />
    [..]
    <fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
          <analyzer type="index">
            <tokenizer class="solr.StandardTokenizerFactory"/>
            <filter class="solr.LowerCaseFilterFactory"/>
            <filter class="solr.EnglishPossessiveFilterFactory"/>
            <filter class="solr.PorterStemFilterFactory"/>
          </analyzer>
          <analyzer type="query">
            <tokenizer class="solr.StandardTokenizerFactory"/>
            <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
            <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_en.txt" />
            <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
            <filter class="solr.LowerCaseFilterFactory"/>
            <filter class="solr.EnglishPossessiveFilterFactory"/>
            <filter class="solr.PorterStemFilterFactory"/>
          </analyzer>
        </fieldType>

person Vilius    schedule 11.01.2014    source источник
comment
Не могли бы вы объяснить, почему ваши стоп-слова часто меняются? Мне интересно, нужен ли здесь другой подход.   -  person Mark Leighton Fisher    schedule 18.01.2014


Ответы (4)


Это не из-за вашего запроса?

http://ip:port/solr/collection1/select?q=*:*&rows=0&facet=true&facet.pivot=year,text

Насколько я могу судить, вы ищете все, а это значит, что он также вернет стоп-слова. То есть, если запрос передается в анализатор, класс фильтра анализатора видит только

*:* 

в качестве запроса, поэтому я не думаю, что таким образом он удалит что-либо из строки запроса.

Если вы действительно хотите искать все, но без каких-либо игнорируемых слов, вы можете попробовать выполнить поиск с помощью отрицательного запроса < / а>. Конечно, если вы используете это, вам понадобится другая конфигурация, которая не фильтрует какие-либо стоп-слова для запроса, тогда вы можете вручную поместить стоп-слова в качестве отрицательного запроса, чтобы отфильтровать их. Таким образом, вы в основном ищете что угодно, но не учитываете результат, содержащий отрицательный запрос.

Но один простой способ (и, по моему мнению, лучший способ) получить то, что вы хотите, - это использовать поле копирования в конфигурации поля. Но это увеличит размер вашего индекса. Итак, что мы делаем здесь с нашим solr, это, помимо обычного поля, у нас есть другие языковые поля, такие как text_en, text_de, text_es и т. Д. И у нас есть детектор языка, который может определять язык, копировать поле на соответствующий язык и запустить правильный фильтр игнорируемых слов.

Вы также можете сделать это, если хотите, в вашем schema.xml просто создайте новое поле text_en_filtered, скопируйте туда текст из text_en и отфильтруйте там стоп-слова. Затем вы можете просто искать в том поле, в котором больше нет стоп-слов.

<field name="text_en_filtered" type="text_en_filtered" indexed="true" stored="false" multiValued="false"/>
<copyField source="text" dest="text_en_filtered"/>
<fieldType name="text_en_filtered" class="solr.TextField" positionIncrementGap="100">
    ... // Analyzer with stopwords filtering here..
</fieldType>
person Rowanto    schedule 14.01.2014

См. Ветку - решает поддерживать только время запроса стоп-слов? из списка рассылки Solr.

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

person Paige Cook    schedule 13.01.2014
comment
при запросе стоп-слов возвращено 0 совпадений ИМХО решение не применяется в этом случае, поскольку StopFilter применяется к самому запросу, поэтому 0 совпадает (что не относится к фасетированию ..) - person Ion Cojocaru; 13.01.2014

Извините, ваш вопрос непонятен. Итак, я предполагаю и пытаюсь ответить на ваш вопрос. Вот как обрабатываются стоп-слова. Если у вас есть <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_en.txt" /> во время индексации, Solr не будет индексировать стоп-слова, и вы не увидите эти слова в полученных фасетах. Кроме того, вам нужно использовать это во время запроса для правильных совпадений.

Если у вас есть <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_en.txt" /> во время запроса, вы удаляете только стоп-слова из фразы запроса, прежде чем Solr выполнит ваш запрос.

Обновление. Ваше неправильное понимание цепочки анализа, похоже, является причиной вашего замешательства. Ваш параметр q - ":", поэтому, если у вас есть StopFilterFactory во время запроса, как упоминалось выше, вы будете фильтровать запрещаемые слова из ":", а не из результатов запроса. В результате вы останетесь с остановленными словами в ваших результатах, так как вы фасетируете текст. Вы должны понимать, что анализ времени запроса выполняется по запросу QUERY, а не по результатам. В вашем «тексте» все еще есть стоп-слова, которые будут отображаться в результатах. В этом случае лучше и легко удалить результаты, которые вам не нужны на стороне клиента.

person Arun    schedule 11.01.2014
comment
Я только что отредактировал свой вопрос. Надеюсь, что теперь все ясно. Я тоже пытался понять ваш ответ, но мне не совсем понятно. - person Vilius; 11.01.2014
comment
Хорошо, переместите фильтр Стоппарда из запроса в индекс и повторно индексируйте. - person Arun; 11.01.2014
comment
Как я уже отмечал, для меня важно удалять стоп-слова во время запроса. Если бы я применил фильтр стоп-слов во время индексации, мне пришлось бы повторно индексировать каждый раз, когда я меняю список стоп-слов. И это не соответствует моим потребностям. - person Vilius; 12.01.2014

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

person Ion Cojocaru    schedule 16.01.2014