Maddie Graham
Maddie Graham

Reputation: 2177

Elasticsearch does not return any values. Django

I'm trying to add a search engine for my blog project using ElasticSearch. I think I did everything correctly (using this tutorial), but whatever I write in the search engine, she always returns no results. My database has records and everything looks good. What can happen? Why can not return any results?

Any help will be very appreciated

My urls.py

from django.conf.urls import url
from . import views
app_name = 'reviews'

urlpatterns = [
    # ex: /
    url(r'^$', views.review_list, name='review_list'),
    # ex: /review/5/
    url(r'^review/(?P<review_id>[0-9]+)/$', views.review_detail, name='review_detail'),
    # ex: /wine/
    url(r'^wine$', views.wine_list, name='wine_list'),
    # ex: /wine/5/
    url(r'^wine/(?P<wine_id>[0-9]+)/$', views.wine_detail, name='wine_detail'),
    url(r'^wine/(?P<wine_id>[0-9]+)/add_review/$', views.add_review, name='add_review'),
    url(r'^review/user/(?P<username>\w+)/$', views.user_review_list, name='user_review_list'),
    url(r'^review/user/$', views.user_review_list, name='user_review_list'),
    url(r'^review/search/$', views.search, name='search'),

]

My views.py

rom django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.urls import reverse
from .models import Review, Wine
from .forms import ReviewForm
import datetime
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from .documents import ReviewDocument



def review_list(request):
    latest_review_list = Review.objects.order_by('-pub_date')[:9]
    context = {'latest_review_list':latest_review_list}
    return render(request, 'reviews/review_list.html', context)


def review_detail(request, review_id):
    review = get_object_or_404(Review, pk=review_id)
    return render(request, 'reviews/review_detail.html', {'review': review})


def wine_list(request):
    wine_list = Wine.objects.order_by('-name')
    context = {'wine_list':wine_list}
    return render(request, 'reviews/wine_list.html', context)


def wine_detail(request, wine_id):
    wine = get_object_or_404(Wine, pk=wine_id)
    form = ReviewForm()
    return render(request, 'reviews/wine_detail.html', {'wine': wine, 'form': form})

@login_required
def add_review(request, wine_id):
    wine = get_object_or_404(Wine, pk=wine_id)
    form = ReviewForm(request.POST)
    if form.is_valid():
        rating = form.cleaned_data['rating']
        comment = form.cleaned_data['comment']
        user_name = request.user.username
        review = Review()
        review.wine = wine
        review.user_name = user_name
        review.rating = rating
        review.comment = comment
        review.pub_date = datetime.datetime.now()
        review.save()
        # Always return an HttpResponseRedirect after successfully dealing
        # with POST data. This prevents data from being posted twice if a
        # user hits the Back button.
        return HttpResponseRedirect(reverse('reviews:wine_detail', args=(wine.id,)))

    return render(request, 'reviews/wine_detail.html', {'wine': wine, 'form': form})

def user_review_list(request, username=None):
    if not username:
        username = request.user.username
    latest_review_list = Review.objects.filter(user_name=username).order_by('-pub_date')
    context = {'latest_review_list':latest_review_list, 'username':username}
    return render(request, 'reviews/user_review_list.html', context)


def search(request):
    q = request.GET.get('q')
    if q:
        reviews = ReviewDocument.search().query("match", title=q)
    else:
        reviews = ''
    return render(request, 'reviews/search.html', {'Review': Review})

My documents.py

from django_elasticsearch_dsl import DocType, Index
from .models import Review

reviews = Index('reviews')


@reviews.doc_type
class ReviewDocument(DocType):
    class Meta:
        model = Review

        fields = [
            'comment',
            'pub_date',
            'user_name',
            'rating',
        ]

My models.py

from django.db import models
import numpy as np


class Wine(models.Model):
    name = models.CharField(max_length=200)

    def average_rating(self):
        all_ratings = [list(map(lambda x: x.rating, self.review_set.all()))]
        return np.mean(all_ratings)

    def __unicode__(self):
        return self.name


class Review(models.Model):
    RATING_CHOICES = (
        (1, '1'),
        (2, '2'),
        (3, '3'),
        (4, '4'),
        (5, '5'),
    )
    wine = models.ForeignKey(Wine, on_delete=models.CASCADE)
    pub_date = models.DateTimeField('date published')
    user_name = models.CharField(max_length=100)
    comment = models.CharField(max_length=200)
    rating = models.IntegerField(choices=RATING_CHOICES)

settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'bootstrap3',
    'reviews',
    'registration',
    'django_elasticsearch_dsl',
]

ELASTICSEARCH_DSL = {
    'default': {
        'hosts': 'localhost:9200'
    },
}

search.html

<form method="get">

  <input id="q" name="q" type="text" placeholder="your search...">

</form>

{% for item in reviews %}

  {{ item.comment }}
  {{ item.pub_date }}
  {{ item.user_name }}
  {{ item.rating }}

  <br>

{% endfor %}

Upvotes: 0

Views: 244

Answers (1)

AdrienF
AdrienF

Reputation: 978

It's hard to pinpoint exactly where things are breaking without running your application. However, here are some pointers that could help you pinpoint the source of the issue. Think of your Django application as several layers (following the MVC pattern):

  • Front-end (view layer): your browser parses and displays the search.html, which has a form on it. The view is what the end user sees and interacts with.

  • Routing (controller layer): urls.py with map from the URL to the right controller function (in views.py). The controller layer is responsible for getting the right data to return to the user.

  • Persistence (model layer): models.py and document.py define abstractions and logic to interact (read from and write to) the data stored in your ElasticSearch instance.

Here you're asking "I do an action in the front-end and I don't get the expected result, where is the issue?". The issue could be in any of the above three layers; you should first try to narrow the issue down to one of those layers.

You should try to answer the following questions:

  • Does your form data make it to the server? (i.e. does the view <> controller interaction work as expected) For this you should use your browser's developer tools to see if you have any error there
  • Is the controller making the right request to the model? For this you should put print statements or breakpoints (see this question) in the the right function in views.py
  • Does the model layer query ElasticSearch in the right way? This a harder to debug because Django hides the details of that from you.

Upvotes: 1

Related Questions