就像使用 Peewee 对数组进行 SQL 查询一样



我有一个PostgreSQL表,它有一个带有标签数组的列(标签列中的数组数据类型)。使用 Peewee(python ORM),我想选择任何标签与列表中任何字符串的部分/子字符串匹配的所有行。

因此,例如,我可以有一个如下所示的列表:

["stan", "tina"]

并且应该匹配表中具有任何标签的所有行afghanistanpakistanstanfordargentina

SQL 查询可能如下所示:

SELECT * FROM media WHERE tags::text LIKE ANY (ARRAY[‘%stan%‘, ‘%tina%‘]);

我将如何使用皮尤来做到这一点?

tags列的建模方式如下:

tags = ArrayField(TextField)

假设您的模型看起来像

from peewee import Model, TextField
from playhouse.postgres_ext import ArrayField

class Media(Model):
tags = ArrayField(TextField)

创建具有非嵌套数组字段的子查询

from peewee import fn
subquery = (Media.select(Media.id.alias('id'),
fn.unnest(Media.tags).alias('unnested_tags'))
.alias('subquery'))

生成标签过滤器,例如

tags = ["stan", "tina"]
tags_filters = [subquery.c.unnested_tags.contains(tag) for tag in tags]
tags_filter = reduce(operator.or_, tags_filters)

最终查询将是

query = (Media.select().join(subquery,
on=subquery.c.id == Media.id)
.filter(tags_filter)
# gets rid of duplicates
.group_by(Media.id))

P. S.:在Python3中,reduce函数可以在functools模块中使用,而在Python 2中,它是一个内置的

最新更新