在Django中使用Postgresql 9.6如何对case和accent不敏感进行排序?

时间:2017-05-15 18:57:44

标签: django postgresql sorting

我想要的是相当于在MySQL中使用In [76]: a=[1,2,3] In [77]: b=[1,2,3] In [78]: c=[1,2,3] In [79]: zip(a,b,c) Out[79]: [(1, 1, 1), (2, 2, 2), (3, 3, 3)] In [80]: map(list, zip(a,b,c)) Out[80]: [[1, 1, 1], [2, 2, 2], [3, 3, 3]] 。所以,如果我有这些字符串(Postgresql的默认排序顺序):

  • 畜舍
  • 气泡
  • BOEUF
  • 牛肉
  • boulette
  • bémol

我希望它们会像这样排序(与MySQL中的utf8_unicode_ci一样):

  • 畜舍
  • 牛肉
  • bémol
  • BOEUF
  • boulette
  • 气泡

这种排序不区分大小写,不区分重音并且连字被转换为多个字符。

我知道Postgresql中的utf8_unicode_ciunaccent,但我不知道如何在Django中使用它们。

Django / Postgresql的可能解决方案:

  • 仅添加新列以进行数据标准化排序(较低,不显示)。
  • 添加索引(like in this answer),但我不确定它如何与Django一起使用?

我不认为全文搜索或Trigram可以帮助我,因为我不一定要根据文本进行搜索,但我需要获得良好的排序顺序。

理想情况下,查询应该很快,因此使用另一个索引列看起来是一个很好的途径。但我希望找到一个解决方案,我不需要为我的数据库中的每个现有文本列实现,这很容易维护,等等。有最佳做法吗?

2 个答案:

答案 0 :(得分:3)

它与Django本身无关,PostgreSQL的lc_collate配置决定了这一点。我建议你回顾一下它的价值:

SHOW lc_collate;

正确的做法是修复此配置。不要忘记查看相关设置(lc_ctype等)。

但是,如果您无法使用正确的设置创建另一个数据库,请尝试在collate上明确ORDER,如下面的测试用例:

CREATE TEMPORARY TABLE table1 (column1 TEXT); 

INSERT INTO table1 VALUES('Barn'),
('beef'),
('bémol'),
('Bœuf'),
('boulette'),
('Bubble');

SELECT * FROM table1 ORDER BY column1 COLLATE "en_US"; --Gives the expected order
SELECT * FROM table1 ORDER BY column1 COLLATE "C"; --Gives "wrong" order  (in your case)

重要的是要记住PostgreSQL依赖于操作系统区域设置。此测试用例在CentOS 7上执行。更多信息herehere

答案 1 :(得分:0)

我是这样的:

但是您需要在PostgreSQL中启用模块“ unaccent ”,然后再执行以下操作:     CREATE EXTENSION unaccent;

def get_value_ci(field):
    return Func(field, function='LOWER', template='UNACCENT(%(function)s(%(expressions)s))')

YoutModel.objects.order_by(get_value_ci('nome_your_field'))

工作,;)