I am building a Django application that contains search engine using elastic search by django_elasticsearch_dsl_drf library. I want to allow user to search for only letters or a part of a word and elastic search returns all words that contain these letters. For example if the user submitted ‘legal’ word the result will be all articles containing ‘legal, legally, illegal, illegally’. I have used nGram tokenizer to make this but it doesn’t work as when I submit the word no results are shown to me.
here is the most important part which is in documents.py:
from django_elasticsearch_dsl import Document, fields, Index
from django_elasticsearch_dsl.registries import registry
from django.conf import settings
from .models import *
from elasticsearch_dsl import analyzer, tokenizer
autocomplete_analyzer = analyzer('autocomplete_analyzer',
tokenizer=tokenizer('trigram', 'nGram', min_gram=1, max_gram=20),
filter=['lowercase']
)
entry_index=Index('entries')
@registry.register_document
class EntryDocument(Document):
title = fields.TextField(
attr='title',
fields={
'raw': fields.TextField(required=True,analyzer=autocomplete_analyzer),
'suggest': fields.CompletionField(),
}
)
body = fields.TextField(
attr='body',
fields={
'raw': fields.TextField(required=True,analyzer=autocomplete_analyzer),
# 'suggest': fields.CompletionField()
}
)
class Index:
name = 'entries'
settings = {
"number_of_shards": 1,
"number_of_replicas": 0,
'max_ngram_diff': 20
}
class Django:
model = entry
fields= []
for more details: models.py:
class entry(models.Model):
title = models.CharField(max_length=600)
body = models.TextField()
Serializers.py:
class EntryDocumentSerializer(DocumentSerializer):
class Meta:
document = EntryDocument
fields = (
'title',
'body',
'entryOrigin'
)
views.py:
class EntryDocumentView(DocumentViewSet):
document = EntryDocument
serializer_class = EntryDocumentSerializer
filter_backends = [
DefaultOrderingFilterBackend,
FilteringFilterBackend,
SearchFilterBackend,
SuggesterFilterBackend,
]
search_fields = (
'title',
'body'
)
filter_fields = {
'title': {
'field' : 'title',
'lookups': [
LOOKUP_FILTER_RANGE,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_GT,
LOOKUP_QUERY_GTE,
LOOKUP_QUERY_LT,
LOOKUP_QUERY_LTE,
],
},
'body': {
'field': 'body',
'lookups': [
LOOKUP_FILTER_RANGE,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_GT,
LOOKUP_QUERY_GTE,
LOOKUP_QUERY_LT,
LOOKUP_QUERY_LTE,
],
},
'entryOrigin': 'entryOrigin.id'
}
suggester_fields = {
'title_suggest': {
'field': 'title.suggest',
'suggesters': [
SUGGESTER_COMPLETION,
],
'options': {
'size': 20, # Override default number of suggestions
'skip_duplicates':True, # Whether duplicate suggestions should be filtered out.
},
},
'body_suggest': {
'field': 'body.suggest',
'suggesters': [
SUGGESTER_COMPLETION,
]}
}
urls.py:
from django.contrib import admin
from django.urls import path,include
from rest_framework import routers
from thesearchable.views import EntryDocumentView
from rest_framework import routers
router = routers.SimpleRouter(trailing_slash=False)
router.register(r'entry-search', EntryDocumentView, basename='entry-search')
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('thesearchable.urls')),
]
urlpatterns += router.urls
So how can I search for only part of the word?