OK, so this turned out to be doable using a custom Lookup. Like so:
from django.contrib.postgres.fields.jsonb import (
KeyTransform, KeyTransformTextLookupMixin
)
from django.db.models.lookups import In
@KeyTransform.register_lookup
class KeyTransformIdIn(KeyTransformTextLookupMixin, In):
lookup_name = 'id_in'
prepare_rhs = False
def as_sql(self, compiler, connection):
lhs_sql, lhs_params = self.process_lhs(compiler, connection)
rhs_sql, rhs_params = self.process_rhs(compiler, connection)
sql = "%s::int IN %s" % (lhs_sql, rhs_sql)
params = [*lhs_params, *rhs_params]
return sql, params
From the KeyTransformTextLookupMixin source code comments:
"""
Mixin for combining with a lookup expecting a text lhs from a JSONField
key lookup. Make use of the ->> operator instead of casting key values to
text and performing the lookup on the resulting representation.
"""
The built in django.db.models.lookups.In class provides the proper right-hand-side processing to convert the list of integers into correct PostgreSQL.
...WHERE ("table"."metadata" ->> 'my_id')::int IN (1234, 3456...
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…