Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to combine multiple querysets and remove duplicates?

I'm using Django 1.6.1 with django-taggit.

I'm trying to extend my search engine so that it searches for keywords in other fields besides the tag fields. The trouble is that when I iterate through the tags for an icontains search in the model's name, the queryset seems to cease being a queryset, losing its count method, and the distinct method doesn't work.

views.py:

def index(request):
    numresources = Resource.objects.count()

    if request.method == 'POST':
        form = SearchForm(request.POST)
        if form.is_valid():
            query = form.cleaned_data['query']
            tags = parse_tags(query.lower())

#            resourcelist = []
#            for tag in tags:
#                resourcelist.extend(Resource.objects.filter(name__icontains=tag).filter(isActive=True).order_by('-score').distinct())
#            resourcelist.extend(Resource.objects.filter(tags__name__in=tags).filter(isActive=True).order_by('-score').distinct())
#            numresults = len(resourcelist)

            resourcelist = Resource.objects.filter(tags__name__in=tags).filter(isActive=True).order_by('-score').distinct()
            querymade = True
            numresults = resourcelist.count()
        else:
            resourcelist = Resource.objects.filter(isActive=True).order_by('-created')[:100]
    else:
        resourcelist = Resource.objects.filter(isActive=True).order_by('-created')[:100]
        form = SearchForm()

    return render(request, 'index.html', locals())

It seems clunky to have to add the 'django' keyword to a record that has 'django' in the title or url. I want to have not only the results whose tags match the keywords the user entered, but I want to search other fields for the keywords entered, combine those querysets, and leave on of any result added twice or more.

So how and when in this process do I sort by score and then remove duplicates?

like image 658
pyrodney Avatar asked Jan 09 '14 07:01

pyrodney


People also ask

How you combine multiple QuerySets in a view?

Use union operator for queryset | to take union of two queryset. If both queryset belongs to same model / single model than it is possible to combine querysets by using union operator. One other way to achieve combine operation between two queryset is to use itertools chain function.

How do I merge two QuerySets in Python?

The Python union operator can be used to combine QuerySets that belong to the same model. You can also use the chain() method from the Itertools module, which allows you to combine two or more QuerySets from different models through concatenation.


1 Answers

I think that you want something like this:

from django.db.models import Q

Resource.objects.filter(Q(name__icontains=tag) | Q(tags__name__in=tags)).filter(isActive=True).order_by('-score').distinct()

Q objects documentation

like image 61
Goin Avatar answered Sep 27 '22 20:09

Goin