如何查询Django ArrayField的长度?

Hri*_*shi 9 django postgresql django-models django-queryset

我在模型中有一个ArrayField,我试图注释该字段的长度(到目前为止没有任何运气)

F('field_name__len')由于不允许在内部加入而无法工作F()。甚至 ModelName.objets.values('field_name__len')不工作

任何的想法?

我正在使用Django 1.11

mar*_*t1n 7

extra()功能已根据docs被弃用:

不得已时使用此方法

这是一个旧的API,我们打算在将来的某个时候弃用。仅当无法使用其他queryset方法表达查询时才使用它。

您可以使用自定义Annotation函数执行以下操作:

from django.db import models

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

MyModel.objects.all().annotate(field_len=ArrayLength('field')).order_by('field_len')
Run Code Online (Sandbox Code Playgroud)

请注意,该cardinality()函数在PostgreSQL 9.4或更高版本中可用。如果您使用的是旧版本,则必须使用array_length()

MyModel.objects.all().annotate(field_len=Func(F('field'), 1, function='array_length')).order_by('field_len')
Run Code Online (Sandbox Code Playgroud)

第二个查询的一个警告是,一个空数组将在所有非空数组之前排序。这可以通过合并NULLarray_length到0的值来解决。

  • 好答案!只是要注意我们也可以直接使用该函数:`.annotate(field_len = Func(F('field'),function ='CARDINALITY'))` (2认同)
  • 请注意,如果您使用 [`django-postgres-extensions`](https://pypi.org/project/django-postgres-extensions/),您已经拥有 [`Cardinality`](https://github.com/django-postgres-extensions/)。 com/primal100/django_postgres_extensions/blob/bb1edc2cbf194fe571a605595a898b2528918301/django_postgres_extensions/models/functions.py#L86)和[`ArrayLength`](https://github.com/primal100/django_postgres_extensions/blob/bb1ed c2cbf194fe571a605595a898b2528918301/django_postgres_extensions/models/functions.py #L74) 功能。 (2认同)

Exp*_*tor 6

ModelName.objects.extra(select={'length':'cardinality(field_name)'}).order_by('length')
Run Code Online (Sandbox Code Playgroud)

你可以试试这个


jmu*_*sch 6

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

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

ModelName.objects.values('field_name__len')

<ModelName [{'field_name__len': 1}]>
Run Code Online (Sandbox Code Playgroud)

还有其他一些可以尝试的事情:

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)
Run Code Online (Sandbox Code Playgroud)