Answer the question
In order to leave comments, you need to log in
Haystack+Solr: How to set up faceted search so that it works using the "OR" method?
Good day to all:
I'm using the latest version of haystack (2.4.1) and solr version 4 (if necessary, I can find out the exact version, but it seems to me that this is not critical).
Set up a faceted search, this is how the index looks like
class SouvenirProductIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
category_title = indexes.CharField(model_attr='base_product__subcategory__category__title', faceted=True)
baseproduct_title = indexes.CharField(model_attr='base_product__title', faceted=True)
subcategory_title = indexes.CharField(model_attr='base_product__subcategory__title', faceted=True)
people_categories = indexes.MultiValueField(faceted=True)
holidays = indexes.MultiValueField(faceted=True)
colors = indexes.MultiValueField(faceted=True)
suggestions = indexes.FacetCharField()
def get_model(self):
return SouvenirProduct
def prepare_people_categories(self, obj):
return [people.style for people in obj.people_categories.all()]
def prepare_holidays(self, obj):
return [holiday.slug for holiday in obj.holidays.all()]
def prepare_colors(self, obj):
colors = []
for product_color in obj.productcolor_set.all():
color = product_color.color
if color.image:
colors.append(color.image.url)
else:
colors.append(color.rgb)
return colors
class ProductSearchView(FacetedSearchView):
template_name = 'search/search.html'
form_class = FacetedNotEmptySearchForm
facet_fields = ['people_categories', 'holidays', 'category_title', 'colors']
<?xml version="1.0" ?>
<schema name="default" version="1.5">
<types>
<fieldtype name="string" class="solr.StrField" sortMissingLast="true" omitNorms="true"/>
<fieldType name="boolean" class="solr.BoolField" sortMissingLast="true" omitNorms="true"/>
<fieldtype name="binary" class="solr.BinaryField"/>
<fieldType name="int" class="solr.TrieIntField" precisionStep="0" omitNorms="true" sortMissingLast="true" positionIncrementGap="0"/>
<fieldType name="float" class="solr.TrieFloatField" precisionStep="0" omitNorms="true" sortMissingLast="true" positionIncrementGap="0"/>
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" sortMissingLast="true" positionIncrementGap="0"/>
<fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" omitNorms="true" sortMissingLast="true" positionIncrementGap="0"/>
<fieldType name="sint" class="solr.SortableIntField" sortMissingLast="true" omitNorms="true"/>
<fieldType name="slong" class="solr.SortableLongField" sortMissingLast="true" omitNorms="true"/>
<fieldType name="sfloat" class="solr.SortableFloatField" sortMissingLast="true" omitNorms="true"/>
<fieldType name="sdouble" class="solr.SortableDoubleField" sortMissingLast="true" omitNorms="true"/>
<fieldType name="tint" class="solr.TrieIntField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="date" class="solr.TrieDateField" omitNorms="true" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="tdate" class="solr.TrieDateField" omitNorms="true" precisionStep="6" positionIncrementGap="0"/>
<fieldType name="point" class="solr.PointType" dimension="2" subFieldSuffix="_d"/>
<fieldType name="location" class="solr.LatLonType" subFieldSuffix="_coordinate"/>
<fieldtype name="geohash" class="solr.GeoHashField"/>
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
<fieldType name="spell_ru" class="solr.TextField" positionIncrementGap="100" omitNorms="true">
<analyzer>
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.HunspellStemFilterFactory" dictionary="ru_RU.dic" affix="ru_RU.aff" ignoreCase="true" />
</analyzer>
</fieldType>
<fieldType name="text_ws" class="solr.TextField" positionIncrementGap="100">
<analyzer>
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
</analyzer>
</fieldType>
<fieldType name="ngram" class="solr.TextField" >
<analyzer type="index">
<tokenizer class="solr.KeywordTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.NGramFilterFactory" minGramSize="3" maxGramSize="15" />
</analyzer>
<analyzer type="query">
<tokenizer class="solr.KeywordTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
<fieldType name="edge_ngram" class="solr.TextField" positionIncrementGap="1">
<analyzer type="index">
<tokenizer class="solr.WhitespaceTokenizerFactory" />
<filter class="solr.LowerCaseFilterFactory" />
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="15" side="front" />
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory" />
<filter class="solr.LowerCaseFilterFactory" />
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
</analyzer>
</fieldType>
</types>
<fields>
<field name="id" type="string" indexed="true" stored="true" multiValued="false" required="true"/>
<field name="django_ct" type="string" indexed="true" stored="true" multiValued="false"/>
<field name="django_id" type="string" indexed="true" stored="true" multiValued="false"/>
<field name="_version_" type="long" indexed="true" stored ="true"/>
<dynamicField name="*_i" type="int" indexed="true" stored="true"/>
<dynamicField name="*_s" type="string" indexed="true" stored="true"/>
<dynamicField name="*_l" type="long" indexed="true" stored="true"/>
<dynamicField name="*_t" type="spell_ru" indexed="true" stored="true"/>
<dynamicField name="*_b" type="boolean" indexed="true" stored="true"/>
<dynamicField name="*_f" type="float" indexed="true" stored="true"/>
<dynamicField name="*_d" type="double" indexed="true" stored="true"/>
<dynamicField name="*_dt" type="date" indexed="true" stored="true"/>
<dynamicField name="*_p" type="location" indexed="true" stored="true"/>
<dynamicField name="*_coordinate" type="tdouble" indexed="true" stored="false"/>
<field name="text" type="spell_ru" indexed="true" stored="true" multiValued="false" />
<field name="holidays" type="spell_ru" indexed="true" stored="true" multiValued="true" />
<field name="category_title" type="spell_ru" indexed="true" stored="true" multiValued="false" />
<field name="category_title_exact" type="string" indexed="true" stored="true" multiValued="false" />
<field name="subcategory_title" type="spell_ru" indexed="true" stored="true" multiValued="false" />
<field name="subcategory_title_exact" type="string" indexed="true" stored="true" multiValued="false" />
<field name="baseproduct_title" type="spell_ru" indexed="true" stored="true" multiValued="false" />
<field name="baseproduct_title_exact" type="string" indexed="true" stored="true" multiValued="false" />
<field name="people_categories" type="spell_ru" indexed="true" stored="true" multiValued="true" />
<field name="suggestions" type="spell_ru" indexed="true" stored="true" multiValued="false" />
<field name="colors" type="spell_ru" indexed="true" stored="true" multiValued="true" />
<field name="colors_exact" type="string" indexed="true" stored="true" multiValued="true" />
<field name="people_categories_exact" type="string" indexed="true" stored="true" multiValued="true" />
<field name="holidays_exact" type="string" indexed="true" stored="true" multiValued="true" />
</fields>
<uniqueKey>id</uniqueKey>
<defaultSearchField>text</defaultSearchField>
<solrQueryParser defaultOperator="OR"/>
</schema>
Answer the question
In order to leave comments, you need to log in
Solution (suddenly someone will come in handy) (I have also done here that if the search string is not set, then all results are displayed):
from collections import defaultdict
from haystack.forms import FacetedSearchForm
class FacetedNotEmptySearchForm(FacetedSearchForm):
def no_query_found(self):
return self.searchqueryset.all()
@property
def selected_multi_facets(self):
selected_multi_facets = defaultdict(list)
for facet_kv in self.selected_facets:
if ":" not in facet_kv:
continue
field_name, value = facet_kv.split(':', 1)
selected_multi_facets[field_name].append(value)
return selected_multi_facets
def search(self):
sqs = super(FacetedSearchForm, self).search()
for field, values in self.selected_multi_facets.items():
if not values:
continue
clean_values = ['"%s"' % sqs.query.clean(val) for val in values]
sqs = sqs.narrow(u'%s:(%s)' % (field, " OR ".join(clean_values)))
return sqs
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question