Вы должны убедиться, что ваше поле сортировки не маркировано в SOLR. Из документации Haystack не очень понятно, как сделать его не токенизированным с помощью Haystack. Мое решение состояло в том, чтобы изменить SOLR schema.xml, сгенерированный Haystack, так, чтобы тип поля был " string " вместо " text ". Поэтому вместо того, чтобы иметь что-то подобное в вашем schema.xml:
<field name="result_title_sort" type="text" indexed="true" stored="true" multiValued="false" />
вам нужно иметь это:
<field name="result_title_sort" type="string" indexed="true" stored="true" multiValued="false" />
Поскольку вы, возможно, много раз регенерируете свой schema.xml, я рекомендую создать сценарий сборки для создания файла схемы, который автоматически изменит схему для вас. Примерно так:
./manage.py build_solr_schema | sed 's/<field name=\"result_title_sort\" type=\"text\"/<field name=\"result_title_sort\" type=\"string\"/' > schema.xml
(или для Haystack 2.0)
./manage.py build_solr_schema | sed 's/<field name=\"name_sort\" type=\"text_en\"/<field name=\"name_sort\" type=\"string\"/' > schema.xml
После того, как я это сделал, моя сортировка работала в алфавитном порядке. Тем не менее, все еще были некоторые проблемы, потому что сортировка выполнялась в порядке ASCII, в котором в конце ставились строчные и нелатинские символы. Поэтому я создал следующий метод для подготовки текста к сортировке, который использует модуль unidecode для преобразования нелатинских символов в ASCII. Также удаляются начальные пробелы, "the" и "a":
def format_text_for_sort(sort_term,remove_articles=False):
''' processes text for sorting field:
* converts non-ASCII characters to ASCII equivalents
* converts to lowercase
* (optional) remove leading a/the
* removes outside spaces
'''
sort_term = unidecode(sort_term).lower().strip()
if remove_articles:
sort_term = re.sub(r'^(a\s+|the\s+)', '', sort_term )
return sort_term
Затем вам нужно добавить метод prepare в ваш search_indexes.py для вызова средства форматирования, что-то вроде
def prepare_result_title_sort(self,obj):
return format_text_for_sort( obj.title, remove_articles=True )