Opened 2 years ago

Closed 2 years ago

Last modified 2 years ago

#35491 closed New feature (invalid)

QuerySet.extra use case. Unnest array and make it lower. and make it an array again.

Reported by: june Owned by: nobody
Component: Database layer (models, ORM) Version: 4.2
Severity: Normal Keywords: QuerySet.extra
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I had used extra() for annotating Arrayfield with lower cases and filter out with another array intersection.

Below is what I used for

`

lower_value = [v.lower() for v in value]
numbers = Numeric.objects.extra(

where=[f"ARRAY(SELECT lower(unnest({array_field}))) && %s::text[]"],
params=[lower_value],

)

`

I need to unnest arrayfield first and make each elements lowercase, and make it an Array again.
and then need to check overlay with another array.

Change History (1)

comment:1 by Simon Charette, 2 years ago

Resolution: → invalid
Status: new → closed

There are multiple ways to achieve that without the usage of extra.

The most straightforward is to use RawSQL ​as mentioned in the docs right below the part that mentions using creating a ticket.

Numeric.objects.filter(
    RawSQL(
        f"ARRAY(SELECT lower(unnest({array_field}))) && %s::text[]",
        (lower_values,)
        output_field=BooleanField(),
    )
)

But you could also use a Func

class ArrayLower(Func):
    template = "ARRAY(SELECT lower(unnest(%(expressions)s)))"
    arity = 1
    output_field = ArrayField(TextField())

Numeric.objects.alias(
    array_field_lower=ArrayLower("array_field")
).filter(
    array_field_lower__overlap=lower_values
)

It would also be pretty straightforward to define an __loweroverlap ​transform if you wanted to to encapsulate all of that logic

Numeric.objects.filter(
    array_field__loweroverlap=value
)

In short, you don't need extra at all to achieve what you're after. Please refer to ​the expression documentation and familiarize yourself with RawSQL usage if you want to resort to raw sql usage.

Last edited 2 years ago by Simon Charette (previous) (diff)
Note: See TracTickets for help on using tickets.
Back to Top