Вопрос

How can I filter by string list in haystack 2.0?

In Haystack 1.2 with Solr, if I have this code:

result = SearchQuerySet().models(MyModel).filter(my_field__in=['A', 'B', 'C'])

Result will exactly return objects with my_field equals to 'A', 'B' or 'C'. Instead, in Haystack 2.0 with Solr we will obtain objects with my_field as 'A', 'A something', 'B', 'B something'. I need preserve the haystack 1.2 behavior. Any idea?

If I use in Haystack 2.0:

result = SearchQuerySet().models(MyModel).filter(my_field=Exact('A'))

I will obtain objects with my_field equals to 'A'. Good! But I do not find one solution for filter with exact values in a list.

I need your help. Thanks you.

Это было полезно?

Решение

I have found one solution. In Haystack 2.0, the schema.xml generated for solr has the next definition related to default text field:

   <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>

In Haystack 1.2, the schema.xml generated for solr has this other definition:

<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>

If you compare the analyzers in both definitions you can check that Haystack 1.2 version use solr.WhitespaceTokenizerFactory, and Haystack 2.0 version use solr.StandardTokenizerFactory.

To keep the behavior of Haystack 1.2 in Haystack 2.0 you can create new text field type named, for example, "text_exact" with the same content of text field definition of Haystack 1.2 and then you associate all text fields in schema.xml with "text_en" to "text_exact".

From this version:

<field name="sales_user" type="text_en" indexed="true" stored="true" multiValued="false" />

We will obtain this other version:

<field name="sales_user" type="text_exact" indexed="true" stored="true" multiValued="false" /> 

The Haystack 2.0 official documentation does not provide a solution to this big change. It would be interesting to include some examples like this in section dedicated to migration from Haystack 1.x to 2.x.

Другие советы

I am using the Haystack 2.4.1. I faced similar problem. The reason is that the field should not be analyzed.

To make the index of field 'not_analyzed' pass indexed parameter as False. So while indexing the field I have used the following parameters.

    field_name = indexes.CharField(model_attr='db_field',indexed=False)

So that field_name will become 'not_analyzed'

After that you apply your query.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top