1

I have models:

ModelA, Conversation  

class ModelA:
     conversations = models.ManyToManyField(Conversation)  

I want to retrieve records of ModelA which has conversations with ids 1,2,3 (lets say).

I tried this:

ModelA.objects.filter(conversations__id__in=[1,2,3])  

But this is not doing exact filter. If record A has only one conversation with id 1, record B with only one conversation with id 2 and record C has 3 conversations with ids 1,2,3, then above code returning all 3 records. But, I want to retrive only record C becaus only that has all the conversations 1,2,3.

I need exact or if possible subset. I mean, If I search for [1,2] then record A, B shouldn't come but record C can come([1,2] is subset of [1,2,3])

Please let me know if not clear.

user2349115
  • 1,288
  • 2
  • 17
  • 34

2 Answers2

1

Referring to Query using contains each value in list, you can do the same thing here with the in field lookup:

from django.db.models import Q
ModelA.objects.filter(reduce(operator.and_, (Q(conversations__id=x) for x in [1,2,3])))

# the above is equivalent to:
ModelA.objects.filter(Q(conversations__id=1) &
                      Q(conversations__id=2) &
                      Q(conversations__id=3))
Community
  • 1
  • 1
pcoronel
  • 3,833
  • 22
  • 25
  • 1
    I think there's no need to use `__in` lookup if there's only single value. Moreover - it might be an ineffective query.`Q(conversation__id=1) & ...)` should be sufficient. – yedpodtrzitko May 28 '14 at 00:10
  • @yedpodtrzitko Ah true, changing the code to use `conversation__id=x`. Also, though the `reduce()` might incur some overhead, it allows for a dynamically generated list to be passed in (*[1,2,3]* was just an example). Thus, something like `reduce(operator.and_, (Q(conversations__id=x) for x in id_list)` is now possible. – pcoronel May 28 '14 at 00:18
0

You need to chain the queries to find those that have at least 1, 2, and 3.

ModelA.objects.filter(conversations=1).filter(conversations=2).filter(conversations=3)

I answered a question like this a long time ago which is still relevant: How to do many-to-many Django query to find book with 2 given authors?

As for your last comment, [1] is a subset of [1, 2] so I'm not quite sure what logic you are attempting to filter by. A subset, but a minimum subset of 2 elements?

Community
  • 1
  • 1
Yuji 'Tomita' Tomita
  • 115,817
  • 29
  • 282
  • 245
  • Its not about 2 elements, when I search for 1,2 both these exist in 1,2,3. This is what I mean by subset. Ofcourse, if you feel its meaningless, leave it. – user2349115 May 28 '14 at 00:07