This should only be used for testing. The index that will be used is created from the bulk_indexing method below.
curl -X PUT 'localhost:9200/<index_name>'
Easy way to check if index was created or deleted.
curl -X GET 'localhost:9200/_cat/indices?v'
If you make any changes to the index you'll need to delete it and rebuild it using the build_indexing method below.
curl -X DELETE 'localhost:9200/<index_name>'
Download and install the public signing key:
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
You can install the ElasticSearch Debian package with:
sudo apt-get update && sudo apt-get install elasticsearch
To configure ElasticSearch to start automatically when the system boots up, run the following commands:
sudo /bin/systemctl daemon-reload
sudo /bin/systemctl enable elasticsearch.service
ElasticSearch can be started and stopped as follows:
sudo systemctl start elasticsearch.service
sudo systemctl stop elasticsearch.service
You can test that your Elasticsearch node is running by sending an HTTP request to port 9200 on localhost:
curl -X GET "localhost:9200/"
Which should give you a response something like this:
{
"name" : "Cp8oag6",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "AT69_T_DTp-1qgIJlatQqA",
"version" : {
"number" : "6.6.0",
"build_flavor" : "default",
"build_type" : "zip",
"build_hash" : "f27399d",
"build_date" : "2016-03-30T09:51:41.449Z",
"build_snapshot" : false,
"lucene_version" : "7.6.0",
"minimum_wire_compatibility_version" : "1.2.3",
"minimum_index_compatibility_version" : "1.2.3"
},
"tagline" : "You Know, for Search"
}
Source: elasticsearch-dsl setup
Install the connector package.
pip install elasticsearch-dsl
Create search.py in your app's folder to connect the app to ElasticSearch, and create the indexing model.
An analyzer is also created here to tokenize any text fields you'll want partial search on. This examples also stripes HTML tags and allows you to search in all upper or lower case letters.
search.py
from elasticsearch_dsl.connections import connections
from elasticsearch_dsl import Document, Text, Date, Integer, analyzer, tokenizer
connections.create_connection()
my_analyzer = analyzer("my_analyzer",
tokenizer = tokenizer("trigram", nGram, min_gram=3, max_gram=10),
filter = ['standard', 'lowercase', 'uppercase'],
char_filter = [ "html_strip" ]
)
class <ModelNameIndex>(Document):
title = Text(analyzer=my_analyzer)
text = Text()
date = Date()
number = Integer()
class Index:
name = '<ModelName>-index'
The Document wrapper enables writing the index like a model, and Text and Date are for formatting the fields when indexed. The Index class tells ElasticSearch what to name the index.
The bulk command is in elasticsearch.helpers which is included with elasticsearch_dsl. Do the following in search.py:
search.py
from elasticsearch.helpers import bulk
from elasticsearch import Elasticsearch
from . import models
def bulk_indexing():
<ModelNameIndex>.init()
es = Elasticsearch()
bulk(client=es, actions=(b.indexing() for b in models.<ModelName>.objects.all().iterator()))
init() maps the update to ElasticSearch. Pass the instance of Elasticsearch() to create the connection. bulk() uses a generator actions= and iterates over all the model objects by calling indexing().
Now create indexing() on your model.
models.py
from .search import <ModelNameIndex>
def indexing(self):
obj = <ModelNameIndex>(
meta={'id': self.id},
title = self.title,
text = self.text,
date = self.date,
number = self.number,
)
obj.save()
return obj.to_dict(include_meta=True)
Complete the bulk indexing using the method below.
Run python manage.py shell
.
import from <AppName>.search import *
.
Then run bulk_indexing()
to index all instances.
A signal is needed that fires indexing(). In the app create a file named signals.py and add:
signals.py
from .models import <ModelName>
from django.db.models.signals import post_save
from django.dispatch import receiver
@receiver(post_save, sender=<ModelName>)
def index_post(sender, instance, **kwargs):
instance.indexing()
The signal needs to be registered in Django. Do this by opening apps.py and adding:
apps.py
from django.apps import <AppNameConfig>
class <AppName>Config(<AppNameConfig>):
name = 'article'
def ready(self):
import <ModelName>.signals
The signals configuration needs to be setup in Django. Do this by opening init.py and adding:
__init__.py
default_app_config = '<AppName>.apps.<AppNameConfig>'
Create a simple search in search.py to find all articles by title:
search.py
from elasticsearch_dsl import Search
def search(title):
s = Search().filter('term', title=title)
response = s.execute()
return response
Run python manage.py shell
.
The import from <AppName>.search import *
and search using:
print(search(title="whatever title name"))
A get request can be used to pass the search.
The request is routed to the search.py search function through views.py.
Where you can pass the 'response' object into the context dictionary and render to a template.
{{template_name}}.html
<form action="{% url 'search_results' %}" method="GET" value="{{request.GET.esearch}}">
<input type="text" name="esearch" placeholder="Search..."/>
</form>
search.py
def search(request):
if request.method == 'GET':
query = request.GET.get('esearch')
s = Search().query(
Q('match', title={'query': query, 'boost': 100}) |
Q('match', content={'query': query, 'boost': 25})
)
response = s.execute()
ctxt = {"response": response}
return render(request, 'article/search_results.html', ctxt)