我想按标题对我的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')
我该如何定义字段,以便对其进行排序?
答案 0 :(得分:5)
谢谢Mark Chackerian,您的解决方案确实可以用于排序。但是我仍然觉得修改自动生成的schema.xml
的输出有点不舒服。我通过使用Solr的< dynamicField> 字段类型找到了解决方案。关于如何使用动态字段,Django-Haystack文档并不是很明确,但基本上如果你只是在dict
SearchIndex
返回的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
的文档中创建一个动态字符串字段,您可以通过该字段对结果进行排序。
答案 1 :(得分:3)
您需要确保您的排序字段在SOLR中是非标记化的。从Haystack文档中可以看出如何使用Haystack进行非标记化。我的解决方案是更改Haystack生成的SOLR schema.xml,使字段类型为“ 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
然后你需要在你的search_indexes.py中添加一个prepare方法来调用格式化程序,比如
def prepare_result_title_sort(self,obj):
return format_text_for_sort( obj.title, remove_articles=True )
答案 2 :(得分:2)
最后,我通过滥用faceted=True
找到了解决方法。它会导致haystack为charfield生成type="string"
字段。它是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')
答案 3 :(得分:1)
如果字符串被标记化(即有空格),Solr将不允许您对字符串列进行排序。我希望你的标题有多个标记(单词),因此错误。
“字符串术语值可以包含任何有效的字符串,但不应该被标记化。值将根据其自然顺序排序。”来自http://lucene.apache.org/java/3_0_3/api/core/org/apache/lucene/search/Sort.html
答案 4 :(得分:0)
只是接受了接受的答案,我发现只需使用FacetCharField而不是CharField来处理我想要排序的文本就足以将其作为字符串输出到模式中,从而使其可以排序。
我对haystack / Solr相当新,所以我不确定使用FacetCharField的其他含义,但这对我有用。