стог сена
Haystack — это библиотека Python, которая обеспечивает модульный поиск для Django. Он имеет API, который обеспечивает поддержку для различных серверных частей поиска, таких как Elasticsearch, Whoosh, Xapian и Solr.
Elasticsearch
Elasticsearch — популярная поисковая система Lucene, способная выполнять полнотекстовый поиск, и она разработана на Java.
В поиске Google используется тот же подход, что и при индексации их данных, и поэтому очень легко получить любую информацию, используя всего несколько ключевых слов, как показано ниже.

Установите Джанго Хейстек и Elasticsearch
Первый шаг — настроить Elasticsearch и запустить его локально на вашей машине. Elasticsearch требует Java, поэтому на вашем компьютере должна быть установлена Java.
Мы собираемся следовать инструкциям с сайта Elasticsearch .
Загрузите архив Elasticsearch 1.4.5 следующим образом:
|
1
|
curl -L -O https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-1.4.5.tar.gz
|
Извлеките его следующим образом:
|
1
|
tar -xvf elasticsearch-1.4.5.tar.gz
|
Затем он создаст пакет файлов и папок в вашем текущем каталоге. Затем мы идем в каталог bin следующим образом:
|
1
|
cd elasticsearch-1.4.5/bin
|
Запустите Elasticsearch следующим образом.
|
1
|
./elasticsearch
|
Чтобы убедиться, что он успешно установлен, перейдите на http://127.0.0.1:9200/ , и вы должны увидеть что-то вроде этого.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
{
«name» : «W3nGEDa»,
«cluster_name» : «elasticsearch»,
«cluster_uuid» : «ygpVDczbR4OI5sx5lzo0-w»,
«version» : {
«number» : «5.6.3»,
«build_hash» : «1a2f265»,
«build_date» : «2017-10-06T20:33:39.012Z»,
«build_snapshot» : false,
«lucene_version» : «6.6.1»
},
«tagline» : «You Know, for Search»
}
|
Убедитесь, что у вас также есть стог сена.
|
1
|
pip install django-haystack
|
Давайте создадим наш проект Django. Наш проект сможет проиндексировать всех клиентов в банке, упрощая поиск и получение данных, используя всего несколько поисковых терминов.
|
1
|
django-admin startproject Bank
|
Эта команда создает файлы, которые предоставляют конфигурации для проектов Django.
Давайте создадим приложение для клиентов.
|
1
2
3
|
cd Bank
python manage.py startapp customers
|
settings.py Конфигурации
Чтобы использовать Elasticsearch для индексации нашего контента, доступного для поиска, нам нужно определить внутренний параметр для стога сена в файле settings.py нашего проекта. Мы собираемся использовать Elasticsearch в качестве нашего бэкенда.
HAYSTACK_CONNECTIONS является обязательным параметром и должен выглядеть следующим образом:
|
1
2
3
4
5
6
7
|
HAYSTACK_CONNECTIONS = {
‘default’: {
‘ENGINE’: ‘haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine’,
‘URL’: ‘http://127.0.0.1:9200/’,
‘INDEX_NAME’: ‘haystack’,
},
}
|
В settings.py мы также собираемся добавить стог сена и клиентов в список installed apps .
|
01
02
03
04
05
06
07
08
09
10
11
|
INSTALLED_APPS = [
‘django.contrib.admin’,
‘django.contrib.auth’,
‘django.contrib.contenttypes’,
‘django.contrib.sessions’,
‘django.contrib.messages’,
‘django.contrib.staticfiles’,
‘rest_framework’,
‘haystack’,
‘customer’
]
|
Создавать модели
Давайте создадим модель для клиентов. У customers/models. py , добавьте следующий код.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
from __future__ import unicode_literals
from django.db import models
# Create your models here.
customer_type = (
(«Active», «Active»),
(«Inactive», «Inactive»)
)
class Customer(models.Model):
id = models.IntegerField(primary_key=True)
first_name = models.CharField(max_length=50, null=False, blank=True)
last_name = models.CharField(
max_length=50, null=False, blank=True)
other_names = models.CharField(max_length=50, default=» «)
email = models.EmailField(max_length=100, null=True, blank=True)
phone = models.CharField(max_length=30, null=False, blank=True)
balance = models.IntegerField(default=»0″)
customer_status = models.CharField(
max_length=100, choices=customer_type, default=»Active»)
address = models.CharField(
max_length=50, null=False, blank=False)
def save(self, *args, **kwargs):
return super(Customer, self).save(*args, **kwargs)
def __unicode__(self):
return «{}:{}».format(self.first_name, self.last_name)
|
Зарегистрируйте свою модель Customer в admin.py следующим образом:
|
1
2
3
4
5
6
|
from django.contrib import admin
from .models import Customer
# Register your models here.
admin.site.register(Customer)
|
Создать базу данных и Super User
Примените ваши миграции и создайте учетную запись администратора.
|
1
2
|
python manage.py migrate
python manage.py createsuperuser
|
Запустите свой сервер и перейдите по адресу http: // localhost: 8000 / admin / . Теперь вы сможете увидеть свою модель клиента там. Идем дальше и добавляем новых клиентов в админку.
Индексирование данных
Чтобы проиндексировать наши модели, мы начинаем с создания SearchIndex . Объекты SearchIndex определяют, какие данные должны быть помещены в поисковый индекс. Каждый тип модели должен иметь уникальный searchIndex .
Объекты SearchIndex — это способ, которым стог сена определяет, какие данные должны быть помещены в поисковый индекс, и обрабатывает поток данных. Чтобы создать SearchIndex , мы собираемся наследовать от indexes.SearchIndex и indexes.Indexable , определяем поля, которые мы хотим сохраните наши данные с помощью и определите метод get_model .
Давайте создадим CustomerIndex чтобы соответствовать моделированию наших Customer . Создайте файл search_indexes.py в каталоге приложения клиентов и добавьте следующий код.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
from .models import Customer
from haystack import indexes
class CustomerIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.EdgeNgramField(document=True, use_template=True)
first_name = indexes.CharField(model_attr=’first_name’)
last_name = indexes.CharField(model_attr=’last_name’)
other_names = indexes.CharField(model_attr=’other_names’)
email = indexes.CharField(model_attr=’email’, default=» «)
phone = indexes.CharField(model_attr=’phone’, default=» «)
balance = indexes.IntegerField(model_attr=’balance’, default=»0″)
customer_status = indexes.CharField(model_attr=’customer_status’)
address = indexes.CharField(model_attr=’address’, default=» «)
def get_model(self):
return Customer
def index_queryset(self, using=None):
return self.get_model().objects.all()
|
EdgeNgramField — это поле в стоге сена SearchIndex которое предотвращает неправильные совпадения, когда части двух разных слов смешиваются друг с другом.
Это позволяет нам использовать функцию autocomplete для проведения запросов. Мы будем использовать автозаполнение, когда начнем запрашивать наши данные.
document=True указывает на основное поле для поиска внутри. Кроме того, use_template=True в text поле позволяет нам использовать шаблон данных для построения документа, который будет проиндексирован.
Давайте создадим шаблон в каталоге шаблонов наших клиентов. Внутри search/indexes/customers/customers_text.txt добавьте следующее:
|
1
2
3
|
{{object.first_name}}
{{object.last_name}}
{{object.other_names}}
|
Переиндексировать данные
Теперь, когда наши данные находятся в базе данных, пришло время поместить их в наш поисковый индекс. Для этого просто запустите ./manage.py rebuild_index . Вы получите итоги того, сколько моделей было обработано и помещено в индекс.
|
1
|
Indexing 20 customers
|
Кроме того, вы можете использовать RealtimeSignalProcessor , который автоматически обрабатывает обновления / удаления для вас. Чтобы использовать его, добавьте следующее в файл settings.py .
|
1
|
HAYSTACK_SIGNAL_PROCESSOR = ‘haystack.signals.RealtimeSignalProcessor’
|
Запрос данных
Мы собираемся использовать шаблон поиска и Haystack API для запроса данных.
Шаблон поиска
Добавьте URL-адреса стога сена в ваш URLconf.
|
1
|
url(r’^search/’, include(‘haystack.urls’)),
|
Давайте создадим наш шаблон поиска. В templates/search.html Добавьте следующий код.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
{% block head %}
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
{% endblock %}
{% block navbar %}
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
<span class="icon-bar">
<span class="icon-bar">
<span class="icon-bar">
</button>
<a class="navbar-brand" href="#">HOME</a>
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav navbar-right">
<li><input type="submit" class="btn btn-primary" value="Add Customer"> </li>
</ul>
</div>
</div>
</nav>
{% endblock %}
{% block content %}
<div class="container-fluid bg-3 text-center">
<form method="get" action="."
{{ form.non_field_errors }}
<div class="form-group">
{{ form.as_p }}
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary" value="Search">
</div>
{% if query %}
<h3>Results</h3>
<div class="container-fluid bg-4 text-left">
<div class="row">
{% for result in page.object_list %}
<div class="col-sm-4">
<div class="thumbnail">
<div class="form-group">
<p>First name : {{result.first_name}} </p>
</div>
<div class="form-group">
<p>Last name : {{result.last_name}} </p>
</div>
<div class="form-group">
<p>Balance : {{result.balance}} </p>
</div>
<div class="form-group">
<p>Email : {{result.email}} </p>
</div>
<div class="form-group">
<p>Status : {{result.customer_status}} </p>
</div>
</div>
</div>
{% empty %}
<p style="text-center">No results found.</p>
{% endfor%}
</div>
</div>
{% endif %}
</form>
</div>
{% endblock %}
|
page.object_list представляет собой список объектов SearchResult который позволяет нам получить отдельные объекты модели, например, result.first_name .
Ваша полная структура проекта должна выглядеть примерно так:

Теперь запустите сервер, перейдите к 127.0.0.1:8000/search/ и выполните поиск, как показано ниже.

Поиск Albert даст результаты всех клиентов с именем Albert . Если ни один клиент не имеет имени Альберт, то запрос даст пустые результаты. Не стесняйтесь поиграть со своими собственными данными.
Haystack API
Haystack имеет класс SearchQuerySet который разработан для упрощения и согласованности выполнения поиска и повторения результатов. Большая часть API SearchQuerySet знакома с ORM QuerySet Django.
В customers/views.py добавьте следующий код:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
from django.shortcuts import render
from rest_framework.decorators import (
api_view, renderer_classes,
)
from .models import Customer
from haystack.query import SearchQuerySet
from rest_framework.response import Response
# Create your views here.
@api_view(['POST'])
def search_customer(request):
name = request.data['name']
customer = SearchQuerySet().models(Customer).autocomplete(
first_name__startswith=name)
searched_data = []
for i in customer:
all_results = {"first_name": i.first_name,
"last_name": i.last_name,
"balance": i.balance,
"status": i.customer_status,
}
searched_data.append(all_results)
return Response(searched_data)
|
autocomplete - это быстрый способ поиска автозаполнения. Он должен быть запущен для полей EdgeNgramField или NgramField .
В приведенном выше Queryset мы используем метод contains чтобы фильтровать наш поиск, чтобы получать только результаты, содержащие наши определенные символы. Например, Al будет получать только данные о клиентах, которые содержат Al . Обратите внимание, что результаты будут получены только из полей, определенных в customer_text.txt file .

Помимо поиска полей contains другие поля, доступные для выполнения запросов, в том числе:
- содержание
- содержит
- точный
- GT
- GTE
- л
- Ге
- в
- начинается с
- EndsWith
- ассортимент
- нечеткий
Вывод
Огромное количество данных производится в любой момент в социальных сетях, здравоохранении, магазинах и других секторах. Большая часть этих данных неструктурирована и разбросана. Elasticsearch может использоваться для обработки и анализа этих данных в форме, которая может быть понята и потреблена.
Elasticsearch также широко используется для поиска контента, анализа данных и запросов. Для получения дополнительной информации посетите сайты Haystack и Elasticsearch .