Стог сена 2 SearchQuerySet с фильтром по списку, совпадающему с точной строкой
Как я могу фильтровать по списку строк в стоге сена 2.0?
В стоге сена 1.2 с Solr, если у меня есть этот код:
result = SearchQuerySet().models(MyModel).filter(my_field__in=['A', 'B', 'C'])
Результат точно вернет объекты с my_field, равным 'A', 'B' или 'C'. Вместо этого в Haystack 2.0 с Solr мы получим объекты с my_field как "A", "A что-то", "B", "B что-то". Мне нужно сохранить поведение стога сена 1.2. Любая идея?
Если я использую в Haystack 2.0:
result = SearchQuerySet().models(MyModel).filter(my_field=Exact('A'))
Я получу объекты с my_field, равным 'A'. Хорошо! Но я не нахожу одно решение для фильтра с точными значениями в списке.
Мне нужна ваша помощь. Спасибо вам.
2 ответа
Я нашел одно решение. В Haystack 2.0 файл schema.xml, созданный для solr, имеет следующее определение, связанное с текстовым полем по умолчанию:
<fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="lang/stopwords_en.txt"
enablePositionIncrements="true"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.EnglishPossessiveFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
<filter class="solr.EnglishMinimalStemFilterFactory"/>
-->
<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"
enablePositionIncrements="true"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.EnglishPossessiveFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
<filter class="solr.EnglishMinimalStemFilterFactory"/>
-->
<filter class="solr.PorterStemFilterFactory"/>
</analyzer>
</fieldType>
В Haystack 1.2, схема.xml, сгенерированная для solr, имеет другое определение:
<fieldType name="text" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_en.txt"/>
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.EnglishPorterFilterFactory" protected="protwords.txt"/>
<filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<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.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.EnglishPorterFilterFactory" protected="protwords.txt"/>
<filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
</analyzer>
</fieldType>
Если вы сравните анализаторы в обоих определениях, вы можете проверить, что версия Haystack 1.2 использует solr.WhitespaceTokenizerFactory, а версия Haystack 2.0 использует solr.StandardTokenizerFactory.
Чтобы сохранить поведение Haystack 1.2 в Haystack 2.0, вы можете создать новый тип текстового поля с именем, например, "text_exact" с тем же содержимым определения текстового поля, что и в Haystack 1.2, а затем связать все текстовые поля в schema.xml с "text_en". "to" text_exact ".
Из этой версии:
<field name="sales_user" type="text_en" indexed="true" stored="true" multiValued="false" />
Мы получим эту другую версию:
<field name="sales_user" type="text_exact" indexed="true" stored="true" multiValued="false" />
Официальная документация Haystack 2.0 не дает решения для этого большого изменения. Было бы интересно включить несколько таких примеров в раздел, посвященный миграции с Haystack 1.x на 2.x.
Я использую стог сена 2.4.1. Я столкнулся с подобной проблемой. Причина в том, что поле не должно анализироваться.
Чтобы индекс поля 'not_analyzed' передал индексированный параметр как False. Поэтому при индексации поля я использовал следующие параметры.
field_name = indexes.CharField(model_attr='db_field',indexed=False)
Так что field_name станет "not_analyzed"
После этого вы применяете свой запрос.