我正在使用StringAgg
如下order
:
# Get order column & annotate with list of credits
if request.POST.get('order[0][name]'):
order = request.POST['order[0][name]']
if order == 'credits_primary':
releases = releases.annotate(credits_primary=StringAgg(
'credits__entity__name',
delimiter=', ',
filter=Q(credits__type='primary'),
ordering='credits__id'
))
elif order == 'credits_secondary':
releases = releases.annotate(credits_secondary=StringAgg(
'credits__entity__name',
delimiter=', ',
filter=Q(credits__type='secondary'),
ordering='credits__id'
))
else:
order = 'title'
# Order releases
if request.POST.get('order[0][dir]') == 'desc':
releases = releases.order_by(F(order).desc(nulls_last=True), 'title')
else:
releases = releases.order_by(F(order).asc(nulls_last=True), 'title')
for release in releases:
try: print(release.credits_primary)
except: pass
try: print(release.credits_secondary)
except: pass
这本身完全按照预期工作:顺序是我期望的,并print
返回我期望的值。
但是,当我在此之前应用 时filter
,如果结果包含相同的 的多个实例release
,credits__entity__name
则尽管使用了 ,该版本的 s 仍会重复或省略,具体取决于所过滤字段有多少个结果distinct
。
以下是filter
我正在应用的影响聚合的(之前应用的StringAgg
):
# Other filters...
# Filter by Search
if request.POST.get('search[value]'):
query = Q()
search = request.POST['search[value]']
query.add(Q(title__icontains=search), Q.OR)
query.add(Q(tags__tag__name__icontains=search), Q.OR)
query.add(Q(credits__entity__name__icontains=search), Q.OR)
releases = releases.filter(query)
# Make sure items aren't repeated
releases = releases.distinct()
不确定我是否理解您的用例,但如果问题在于您的聚合中出现重复项,也许您可以尝试
distinct
在字符串聚合上使用:https://docs.djangoproject.com/fr/5.1/ref/contrib/postgres/aggregates/#stringagg
过滤器查看(其他)一对多或多对多关系。这意味着这将导致
LEFT OUTER JOIN
开始充当乘数。其他聚合(例如SUM
和 )也同样适用COUNT
。事实上,如果你只是聚合,查询看起来像这样:
这很好,因为我们想要聚合实体,因此每次发布我们都会得到所有实体。
但是现在如果我们例如按标签进行过滤,它看起来像:
这意味着,如果两个标签中的一个匹配,则发布的实体名称将重复一次,但如果两个标签都匹配,则将包含两次。
这
Q(credits__entity__name__icontains)
让情况变得更糟:因为这将加入表格c
,因此credits
具有两个或更多匹配项的实体将被包含多次,而与给定信用不匹配的版本的实体将不再被包括在内。所有这些现象中最不常见的分界点可能是,在进行聚合时应非常
JOIN
小心,尤其是当涉及到多个进行 JOIN 的表时。您可能需要做的是创建一个
Subquery
表达式 [Django-doc],因此它不受“外部”表和相应的影响JOIN
。