2016-07-27 161 views
1

我写了一个基于折以下过滤器的答案在这里提供:Django filter queryset __in for *every* item in list在Django返回更多的结果比预期的查询列表,以一个多对多场

Distinct_Alert.objects.filter(entities__in=relevant_entities, alert_type=alert_type).annotate(num_entities=Count('entities')).filter(
     num_entities=len(relevant_entities)) 

是我遇到的问题是,它似乎过滤不当,有时候它会匹配子列表,我正在使用获取明确的警报,但我注意到其中一些错误,因为他们返回多个匹配,这是罪魁祸首。

[2016-07-27 18:02:23,473: WARNING/Worker-4] [<Entity: DOGE>, <Entity: 8.8.8.8>] 
[2016-07-27 18:02:23,474: WARNING/Worker-4] [<Entity: potato>, <Entity: DOGE>, <Entity: 8.8.8.8>] 
[2016-07-27 18:02:23,475: WARNING/Worker-4] [<Entity: desktop_potato>, <Entity: DOGE>, <Entity: 8.8.8.8>] 

我的实体名单应该只包含

[<Entity: DOGE>, <Entity: 8.8.8.8>] 

,但它在其他两个莫名其妙的匹配。任何帮助,将不胜感激

,我想出了一个临时的黑客是这样的:

for alert in distinct_alert_query.all(): 
      if alert.entities.all().count() == len(relevant_entities) and all([entity in relevant_entities for entity in alert.entities.all()]): 
       distinct_alert = alert 
       break 

其中distinct_alert_query指的是上面提到的很长的查询。这样做的问题是,如果查询的上一集比relevant_entities更大的实体的Distinct_Alerts匹配会打破:(

型号:

class Distinct_Alert(models.Model): 
    #alert_type = models.ForeignKey(Alert_Type, on_delete=models.CASCADE) for the sake of this problem and the filter, this isn't really needed. 
    entities = models.ManyToManyField(to='Entity', through='Entity_To_Alert_Map') 

class Entity(models.Model): 
    label = models.CharField(max_length=700, blank=False) 
    #entity_type = models.ForeignKey(Entity_Type_Label) not necessary for this problem 
    related_entities = models.ManyToManyField('self') 

class Entity_To_Alert_Map(models.Model): 
    entity = models.ForeignKey(Entity, on_delete=models.CASCADE) 
    distinct_alert = models.ForeignKey(Distinct_Alert, on_delete=models.CASCADE) 
    entity_alert_relationship_label = models.ForeignKey(Entity_Alert_Relationship_Label, on_delete=models.CASCADE) 

    class Meta: 
     unique_together = ('entity', 'distinct_alert', 'entity_alert_relationship_label') 
+0

请展示模型。 –

+0

@VladimirDanilov编辑包括模型。 –

+0

@VladimirDanilov每个distinct_alert都有一个实体字段,它有一堆实体对象。 –

回答

1

试试这个:

from django.db.models import IntegerField, Case, When, F 

Distinct_Alert.objects.filter(
    alert_type=alert_type 
).annotate(
    num_entities=Count('entities'), 
    num_relevant_entities=Count(
     Case(When(entities__in=relevant_entities, then=1), 
      default=None, 
      output_field=IntegerField()), 
    ), 
).filter(
    num_entities=F('num_relevant_entities'), 
    num_relevant_entities=len(relevant_entities), 
) 

您查询:

Distinct_Alert.objects.filter(
    entities__in=relevant_entities, 
    alert_type=alert_type 
).annotate(
    num_entities=Count('entities') 
).filter(
    num_entities=len(relevant_entities) 
) 

Order of annotate() and filter() matters

+0

嘿弗拉基米尔,这对我来说不太合适,它似乎根本没有被过滤,实际上它会返回超过300个Distinct_Alerts而不是我之前得到的3个。 –

+0

@ Stupid.Fat.Cat编辑。谢谢! –

+0

谢谢@Vladimir!乍一看,它似乎像一个魅力。但我的上帝看起来很复杂。再次,感谢一堆 –