Джанго-стог сена результаты сортировки по названию - PullRequest
3 голосов
/ 13 сентября 2011

Я бы хотел отсортировать результаты моего запроса django-haystack по названию.

from haystack.query import SearchQuerySet
for result in SearchQuerySet().all().order_by('result_title_sort'):
    print result.result_title_sort

Я продолжаю получать эту ошибку, однако:

есть больше терминов, чемдокументы в поле "result_title_sort", но невозможно сортировать по токенизированным полям

Это мое определение поля стога сена:

result_title_sort = CharField(indexed=True, model_attr='title')

Как определить поле, чтобы я мог определитьсортировать по ней?

Ответы [ 5 ]

5 голосов
/ 07 мая 2012

Спасибо Марк Чакериан, ваше решение действительно работает для сортировки. Однако я все еще чувствовал себя немного некомфортно, изменяя вывод автоматически сгенерированного schema.xml. Я нашел решение, используя типы полей Solr . В документах Django-Haystack не очень ясно, как использовать динамические поля, но в основном, если вы просто включите новый ключ в dict, возвращаемый SearchIndex 's prepare(), и dynamicField будет быть добавленным в документ во время индекса.

Удалить существующий атрибут из SearchIndex

#result_title_sort = CharField(indexed=True, model_attr='title') 
def prepare(self, obj):
    prepared_data['result_title_sort_s'] #notice the "_s"

Вышеуказанное создаст в документе динамическое строковое поле с именем result_title_sort_s, по которому вы сможете сортировать результаты.

3 голосов
/ 09 января 2012

Вы должны убедиться, что ваше поле сортировки не маркировано в 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 )
2 голосов
/ 10 января 2012

В конце концов я нашел способ обойти это путем злоупотребления faceted=True. Это заставляет стог сена генерировать поле type="string" для поля char. Это единственное, что меняется в SOLR schema.xml

result_title_sort = CharField(indexed=True, faceted=True)

def prepare_result_title_sort(self, article):
    return slugify(article.title.lower())

и результат теперь можно отсортировать:

results = results.order_by('result_title_sort_exact')
1 голос
/ 13 сентября 2011

Solr не позволит вам сортировать по строковому столбцу, если строка является токенизированной (то есть имеет пробелы). Я ожидаю, что ваши заголовки содержат более одного токена (слова), следовательно, ошибка.

"Значения строкового члена могут содержать любую допустимую строку, но не должны быть разбиты на токены. Значения сортируются в соответствии с их естественным порядком." От http://lucene.apache.org/java/3_0_3/api/core/org/apache/lucene/search/Sort.html

0 голосов
/ 31 марта 2016

Просто следуя принятому ответу, я обнаружил, что простого использования FacetCharField вместо CharField для текста, по которому я хочу отсортировать, было достаточно, чтобы вывести его в виде строки в схеме и таким образом сделать его сортируемым.

Я довольно новичок в стоге сена / Solr, поэтому я не уверен в других последствиях использования FacetCharField, но это сработало для меня.

...