组合两个查询集,具有不同值的公共字段

Posted

技术标签:

【中文标题】组合两个查询集,具有不同值的公共字段【英文标题】:Combine two querysets, common field with different values 【发布时间】:2020-10-05 16:05:11 【问题描述】:

我在模型“ConsultantProfile”中搜索,相关性由“queryset1”中名为“rank”的字段表示。

我还在相关模型中搜索并从“queryset2”中的相关模型中收集“ConsultantProfile”对象,并为它们手动设置排名“0.7”,以便我可以合并查询集。

当我想合并和合并 queryset1 和 queryset2 时,常见的对象有不同的排名值。问题是在最终的“查询集”中,“排名”字段的值是来自第一个查询集的排名值,我无法为“排名”选择最高值

queryset1 = qs.filter(active=True).annotate(
    rank=SearchRank(
        vector,
        query,
        normalization=Value(2).bitor(Value(4)),
    )
)

ids: some "ConsultantProfile" objects ids

queryset2 = ConsultantProfile.objects.filter(id__in=ids, active=True).annotate(rank=Value(5, FloatField()))

queryset = queryset1 | queryset2

失败的解决方案 我试图通过手动迭代查询集和联合来解决问题,但没有任何改变!

queryset = queryset1.none()

for obj in queryset1:
    qs2_object_qs = queryset2.filter(id=obj.id)

    # object presents in queryset2
    if qs2_object_qs.exists():

        # obj from queryset1 has better rank than queryset2 obj
        if obj.rank >= qs2_object_qs.first().rank:k)
            queryset |= queryset1.filter(id=obj.id)
            queryset2 = queryset2.exclude(id=obj.id)
        else:
            queryset |= qs2_object_qs

    # object does not present in queryset2
    else:
        queryset |= queryset1.filter(id=obj.id)

for obj in queryset2:
    qs_object_qs = queryset.filter(id=obj.id)

    # object presents in queryset
    if qs_object_qs.exists():
        # because compared mutual objects in previous loop and removed
        pass
    else:
        queryset |= queryset2.filter(id=obj.id)

【问题讨论】:

【参考方案1】:

应该在“|”操作数旁边使用union()。 在 union 方法中重复的对象不会被删除。但是在 order('-rank') distinct() 之后将不起作用。

我所做的是我在“|”操作数结果中找到了公共对象,并从它的查询集中删除了排名较低的对象,然后使用联合函数。

temp_queryset = queryset1 | queryset2

for obj in temp_queryset:
    try:
        qs1_object = queryset1.get(id=obj.id)
        qs2_object = queryset2.get(id=obj.id)
        if qs1_object.rank > qs2_object.rank:
            queryset2 = queryset2.exclude(id=obj.id)
        else:
            queryset1 = queryset1.exclude(id=obj.id)
    except ConsultantProfile.DoesNotExist:
        pass

queryset = queryset1.union(queryset2)

queryset = queryset.order_by('-rank')

【讨论】:

以上是关于组合两个查询集,具有不同值的公共字段的主要内容,如果未能解决你的问题,请参考以下文章

SQL,仅结合两个具有不同值的表(仅基于三个字段,而不是整行)

猫鼬查询具有不同值的相同字段

合并两个没有公共字段的表

需要查询两个字段的不同组合,以及出现不同组合的计数

如何在SAS中对不同公共变量的观测值进行求和

具有公共值的 XML SelectNodes,迭代