2011-09-13 55 views
3

我想按標題排序我的django-haystack查詢的結果。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') 

我應該怎麼定義在這個領域,所以我可以對它進行分類?

回答

3

您需要確保您的排序字段在SOLR中未被標記。 Haystack文檔中不太清楚如何使用Haystack將其非標記化。我的解決方案是更改Haystack生成的SOLR schema.xml,以便字段類型爲「字符串」而不是「文本」。因此,而不是在你的schema.xml中是這樣的:

你需要有這樣的:

<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 

(或草堆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。它也消除了初始空間「的」和「一」:

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加準備方法調用格式化,像

def prepare_result_title_sort(self,obj): 
    return format_text_for_sort(obj.title, remove_articles=True) 
+1

儘管我發現了一種使用純粹的Hackstack代碼(下面發佈)的解決方法/ hack,但我喜歡你的解決方案,因爲它不涉及破解。標記爲答案! – vdboor

+0

我認爲對Haystack源有所貢獻,並添加了另一種字符串形式,但我意識到Haystack的目的是有限的,因此它可以是搜索引擎不可知論的,這實際上只是SOLR的特殊性。所以我認爲將修補程序應用於模式會更好。 –

+0

那麼我仍然認爲將這個用例討論給乾草堆開發人員很有用。他們可能會想出一個不可知論的解決方案。至少他們應該瞭解真實世界的問題,以便他們改進。 – vdboor

2

最後我通過濫用faceted=True找到了解決方法。它會導致haystack爲charfield生成一個type="string"字段。這是SOLR模式中唯一改變的東西。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

+1在haystack中查看solr_backend代碼,似乎這個解決方案是通過設計實現的。 – fsw

5

謝謝你馬克Chackerian,您的解決方案不工作排序。但是,我仍然覺得修改自動生成的schema.xml的輸出仍然有點不舒服。我通過使用Solr的<dynamicField>字段類型找到了解決方案。 Django-Haystack文檔並不清楚如何使用動態字段,但基本上如果您只是在dict中包含的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該文件由你就能將結果排序中創建一個動態的字符串字段。

+0

偉大的洞察力,謝謝! :) – vdboor

0

只是接受答案的後續工作,我發現只需使用FacetCharField而不是CharField作爲要排序的文本就足以在模式中將其輸出爲字符串,從而使其可排序。

我對haystack/Solr相當陌生,所以我不確定使用FacetCharField的其他含義,但這對我有用。