Monday, February 20, 2017

Re: Implementing a basic search for my website

Hi Carlo,

 

On Monday 20 February 2017 07:33:08 Carlo Ascani wrote:

 

> class ASearch(ListView):

> model = A

> template_name = 'search_result.html'

>

> def get_context_data(self, **kwargs):

> context = super(A, self).get_context_data(**kwargs)

> results = A.objects.all()

> query = self.request.GET.get('q')

>

> if query:

> query_list = query.split()

>

> results = results.filter(

> reduce(operator.or_, (

> Q(roles__name__icontains=q)

> for q in query_list)) |

> reduce(operator.or_, (

> Q(location__name__iexact=q)

> for q in query_list))

> )

>

> context.update({

> 'results': results

> })

> return context

 

I think in itself your logic is already becoming complex. With the added condition, which is in essence "scoring the results" a simple ordering can't be done here. It really is worth looking into Full Text Search options of your database engine or use an external service for it.

 

If you feel like doing it this way anyway, I would do the reordering in python - databases have invented FTS for this for a good reason: reordering a result set almost always involves doing temporary tables, especially if the ordering conditions are not a table field, but a condition of the results.

 

The good thing is that the sorting is in fact a split: if both have a match, move to top, else move to bottom, so a classic Tail Queue will work.

 

And that also makes using Ludovic's suggestion viable: use 2 queries. One anding the 2 conditions, which should be fast and the second somewhat more complex: where NOT the anded condition and the OR condition.

 

Which to pick, is really a matter of performance: which method does best under pressure and what resource can you scale cheaper / faster?

--

Melvyn Sopacua

No comments:

Post a Comment