如何在Peewee中索引由`array_agg`生成的数组?

huangapple go评论69阅读模式
英文:

How Can I Index an Array Produced by array_agg in Peewee

问题

我试图访问由PostgreSQL的array_agg创建的Peewee .select_from中包含的数组的第一个元素。

这是查询的简化版本:

rows = list(ST.select_from(fn.array_agg(ST.c.sitename)[1].alias("sitename"))
 .join(LS, on=ST.c.id == LS.site)
 .join(L, on=LS.location == L.id)
 .group_by(L).with_cte(ST).objects().dicts())

站点(ST)和位置(L)通过中间表LS具有多对多的关系。 ST是一个公共交通工具,因为它是带有特定条件的Site表的精简版本。

这里返回的相关SQL是

SELECT (array_agg("ST"."sitename") = 1) AS "sitename"

而我想要的SQL是

SELECT (array_agg("ST"."sitename"))[1] AS "sitename"

从我所查找到的信息来看,似乎可以使用[]对ArrayField进行索引,但我假设fn.array_agg()的结果不是ArrayField。我想知道如何对fn.array_agg()的结果进行索引,或者如何将其转换为ArrayField以便使用[]进行索引。

英文:

I'm trying to access the first element of an array that is contained within a peewee .select_from and created by a postgresql array_agg.

Here is a simplified version of the query:

rows = list(ST.select_from(fn.array_agg(ST.c.sitename)[1].alias("sitename"))
 .join(LS, on=ST.c.id == LS.site)
 .join(L, on=LS.location == L.id)
 .group_by(L).with_cte(ST).objects().dicts())

Sites (ST) and locations (L) have a many-to-many relationship through an intermediary table LS. ST is a cte because it is a filtered down version of the Site table with certain criteria.

The relevant SQL being returned here is

 SELECT (array_agg("ST"."sitename") = 1) AS "sitename"

Instead I want the sql to be

SELECT (array_agg("ST"."sitename"))[1] AS "sitename"

It seems that you can index into an ArrayField using [] from the Googling I did, but I'm assuming the result of fn.array_agg() isn't an ArrayField. I would like to know how to index into the results of an fn.array_agg(), or how to convert it into an ArrayField in order to index into it using [].

答案1

得分: 1

这是Peewee目前相当晦涩的部分 - 请原谅。部分原因是因为Postgres坚持在索引之前将函数包装在括号中,这迫使Peewee试图消除多余的括号,这就需要额外的解决方法。无论如何,这是一种方法:

p1, p2, p3 = [Post.create(content='p%s' % i) for i in '123']
Comment.create(post=p1, comment='p1-c1')
Comment.create(post=p1, comment='p1-c2')
Comment.create(post=p2, comment='p2-c1')

idx = NodeList([
    SQL('(array_agg('),
    Comment.comment,
    SQL('))[%s]', (1,))])

query = (Post
         .select(Post, idx.alias('comment'))
         .join(Comment, JOIN.LEFT_OUTER)
         .group_by(Post)
         .order_by(Post.content))
# p1 p1-c1
# p2 p2-c1
# p3 None

请注意,这是一段Python代码,对Peewee和Postgres的某些特定问题进行了处理。

英文:

This is annoyingly obtuse with Peewee at present - my apologies. Part of this is due to Postgres' insistence that the function be wrapped in parentheses before it can be indexed -- peewee tries to eliminate redundant parentheses, which forces an additional workaround. At any rate, here is one way:

p1, p2, p3 = [Post.create(content='p%s' % i) for i in '123']
Comment.create(post=p1, comment='p1-c1')
Comment.create(post=p1, comment='p1-c2')
Comment.create(post=p2, comment='p2-c1')

idx = NodeList([
    SQL('(array_agg('),
    Comment.comment,
    SQL('))[%s]', (1,))])

query = (Post
         .select(Post, idx.alias('comment'))
         .join(Comment, JOIN.LEFT_OUTER)
         .group_by(Post)
         .order_by(Post.content))
# p1 p1-c1
# p2 p2-c1
# p3 None

huangapple
  • 本文由 发表于 2023年2月14日 08:46:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/75442505.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定