CaptainJack
CaptainJack

Reputation: 35

How to make search more accurate in Django?

so on the way of learning process, I am making my first side-project on django.

I want to make my search more accurate, for example: when post body contains text with 3 words "I love stackoverflow" and someone searches for "I stackoverflow" (without word LOVE), result is not shown on the search page.

What could be the best approach in this case to get the result, even if the post body does not contain words in that order as a search query?

views.py

def search(request):
posts = Post.objects.all().order_by('title')
query = request.GET.get('q')
print(query)
if query:
    posts = Post.objects.filter(
        Q(title__icontains=query)|
        Q(body__icontains=query)
    )
context = {
    "posts": posts,
}
return render(request, "search.html", context)

Upvotes: 0

Views: 470

Answers (3)

Wariored
Wariored

Reputation: 1343

Try to split your query

from itertools import chain

def search(request):
    posts = Post.objects.all().order_by('title')
    query = request.GET.get('q')
    if query:
        words = query.split(" ")
        results = []
        for word in words:
            match = posts.filter(
                Q(title__icontains=word)|
                Q(body__icontains=word)
            )
            if match:
                results.append(match)
        posts = set(chain(*results))

    context = {
        "posts": posts,
    }
return render(request, "search.html", context)

Upvotes: 0

jabez
jabez

Reputation: 906

I'd recommend using full text search with django haystack with any search engine. But, to respond to your case, something like following would do the trick, though is not very optimised:

from django.db.models import Q

# consider only words which are having a length greater than 2
# also, words should be sanitised and cleaned before using for db queries.
# use a form for that.
parts = [i for i in request.GET.get('q').split(' ') if len(i) >= 3] 

qs = Q()
query = [qs | Q(title__icontains=query) | Q(body__icontains=query) for q in parts]
result = Post.objects.filter(query).order_by().distinct()

Upvotes: 1

m0etaz
m0etaz

Reputation: 1003

Django provides multiple efficient ways to search on a postgreSQL database that you can find on the official docs.

Upvotes: 0

Related Questions