如何查询Django ArrayField的长度?

22

我有一个模型中的ArrayField,在尝试注释这个字段的长度时遇到了问题(目前还没有成功)

F('field_name__len')不起作用,因为在F()内不允许连接(join)。即使是 ModelName.objets.values('field_name__len')也不起作用。

有什么想法吗?

我使用的是 django 1.11


你能发布一下你正在尝试查询的列的内容吗? - Exprator
[112,113,114,115,116,117] - Hrishi
3个回答

29

根据文档extra()函数已被弃用:

只有在无法使用其他查询集方法表达查询时才能使用此方法。

这是一个旧的API,我们将来会逐步淘汰它。

以下是如何使用自定义的Annotation函数实现相同的功能:

from django.db import models

class ArrayLength(models.Func):
    function = 'CARDINALITY'

MyModel.objects.all().annotate(field_len=ArrayLength('field')).order_by('field_len')

请注意,cardinality() 函数仅适用于 PostgreSQL 9.4 或更新版本。如果您使用较旧的版本,则需要使用array_length()

MyModel.objects.all().annotate(field_len=Func(F('field'), 1, function='array_length')).order_by('field_len')

使用第二个查询的一个注意点是,空数组将排在所有非空数组前面。这可以通过将array_length中的NULL值合并为0来解决。


10
很好的回答!只想指出我们也可以直接使用函数:.annotate(field_len=Func(F('field'), function='CARDINALITY')) - tutuDajuju
5
请注意,如果您正在使用django-postgres-extensions,则已经具备了CardinalityArrayLength函数。 - awesoon

6
ModelName.objects.extra(select={'length':'cardinality(field_name)'}).order_by('length')

你可以尝试这个


6

测试通过django 3.5,您的查询现在可以工作了!

我不确定是哪个版本添加了这个功能,但您可以尝试一下,或者如果可以的话,请尝试升级。

ModelName.objects.values('field_name__len')

<ModelName [{'field_name__len': 1}]>

另外还有一些其他值得尝试的方法:

ModelName.objects.filter(field_name__len__gt=0)
ModelName.objects.filter(field_name__len__gte=0)
ModelName.objects.filter(field_name__len=0)
ModelName.objects.filter(field_name__len__lte=10)
ModelName.objects.filter(field_name__len__lt=10)

此功能自Django 2.0版本起已经可用。文档链接:https://docs.djangoproject.com/en/stable/ref/contrib/postgres/fields/#len - scūriolus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接