简体   繁体   English

使用 django 在 postgres ArrayField 上进行不区分大小写的搜索

[英]Case-insensitive search on a postgres ArrayField with django

In the Django documentation for ArrayField , it lists a contains field lookup. 在 ArrayField 的 Django 文档中,它列出了一个contains字段查找。 However, no icontains (case insensitive lookup - many other fields have it) lookup is present in ArrayField.但是, icontains中没有 icontains(不区分大小写的查找 - 许多其他字段都有)查找。

I need a case-insensitive lookup function for ArrayField, similar to the pre-existing contains lookup.我需要 ArrayField 的不区分大小写的查找函数,类似于预先存在的contains查找。

You can do a case-insensitive look-up using icontains , by omitting the square brackets you would use for contains :您可以使用icontains进行不区分大小写的查找,方法是省略您将用于contains的方括号:

queryset = my_model.objects.filter(field_name__icontains='my_substring')

This works because Postgres casts the ArrayField to text and then checks for 'my_substring' as a substring of the array's text representation.这是有效的,因为 Postgres 将 ArrayField 转换为文本,然后检查“my_substring”作为数组文本表示的子字符串。 You can see this by examining the resulting query:您可以通过检查生成的查询来了解这一点:

print(queryset.query)

# raw SQL output:
'SELECT ... WHERE UPPER("my_model"."field_name"::text) LIKE UPPER(%my_substring%)

This worked for me in Postgres 10.1.这在 Postgres 10.1 中对我有用。


As an addendum, I should disclose that this approach caused a bug for my project.作为附录,我应该披露这种方法导致我的项目出现错误。 Say you want to check if the array field contains 'my_substring' :假设您想检查数组字段是否包含'my_substring'

field_name__icontains='my_substring'

This will retrieve 'my_substring' , but it will also retrieve 'foo_my_substring' .这将检索'my_substring' ,但它也会检索'foo_my_substring' This has to do with the string casting mentioned above.这与上面提到的字符串转换有关。 Use at your own risk.使用风险自负。

icontains , iexact are only applied on string type: icontainsiexact仅适用于字符串类型:

my_array_field__contains=['H'] 

check if ['H'] is included in my_array_field检查 ['H'] 是否包含在 my_array_field 中

But if you try the following, it will works:但是,如果您尝试以下操作,它将起作用:

my_array_field__0__icontains='H'

because it check if the first element contains H or h因为它检查第一个元素是否包含H 或 h

You can query case-insensive search for array like this:您可以像这样查询不区分大小写的数组搜索:

select 'tartu' ILIKE ANY (array['Tallinn', 'Tartu','Narva']);

In Django:在 Django 中:

MyModel.objects.extra(
    where=['%s ILIKE ANY (array_column_name)'],
    params=['tartu', ]
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM