Elasticsearch нь Java хэл дээр бичигдсэн, Lucene ашигладаг json rest api-тай хайлтын систем юм. Энэ хөдөлгүүрийн бүх давуу талуудын тайлбарыг эндээс авах боломжтой
Баримт бичгийн мэдээллийн сангаас нарийн төвөгтэй хайлт хийхэд ижил төстэй хөдөлгүүрүүдийг ашигладаг. Жишээлбэл, хэлний морфологийг харгалзан хайх эсвэл гео координатаар хайх.
Энэ нийтлэлд би блог нийтлэлийг индексжүүлэх жишээг ашиглан ES-ийн үндсүүдийн талаар ярих болно. Би бичиг баримтыг хэрхэн шүүх, эрэмбэлэх, хайх талаар танд үзүүлэх болно.
Үйлдлийн системээс хамаарахгүйн тулд би бүх хүсэлтийг ES-д CURL ашиглан хийх болно. Мөн google chrome-д зориулсан залгаас байдаг
Текст нь баримт бичиг болон бусад эх сурвалжийн холбоосыг агуулна. Төгсгөлд нь баримт бичигт хурдан нэвтрэх холбоосууд байна. Танихгүй нэр томъёоны тодорхойлолтыг эндээс олж болно
ES суулгаж байна
Үүний тулд бидэнд эхлээд Java хэрэгтэй. Хөгжүүлэгчид
ES түгээлтийг эндээс авах боломжтой bin/elasticsearch
. Мөн боломжтой
Суулгаж, ажиллуулсны дараа функцийг шалгацгаая:
# для удобства запомним адрес в переменную
#export ES_URL=$(docker-machine ip dev):9200
export ES_URL=localhost:9200
curl -X GET $ES_URL
Бид иймэрхүү зүйлийг хүлээн авах болно:
{
"name" : "Heimdall",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "2.2.1",
"build_hash" : "d045fc29d1932bce18b2e65ab8b297fbf6cd41a1",
"build_timestamp" : "2016-03-09T09:38:54Z",
"build_snapshot" : false,
"lucene_version" : "5.4.1"
},
"tagline" : "You Know, for Search"
}
Индексжүүлэх
ES-д нийтлэл нэмье:
# Добавим документ c id 1 типа post в индекс blog.
# ?pretty указывает, что вывод должен быть человеко-читаемым.
curl -XPUT "$ES_URL/blog/post/1?pretty" -d'
{
"title": "Веселые котята",
"content": "<p>Смешная история про котят<p>",
"tags": [
"котята",
"смешная история"
],
"published_at": "2014-09-12T20:44:42+00:00"
}'
серверийн хариу:
{
"_index" : "blog",
"_type" : "post",
"_id" : "1",
"_version" : 1,
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"created" : false
}
ES автоматаар үүсгэгдсэн
# Получим mapping всех типов индекса blog
curl -XGET "$ES_URL/blog/_mapping?pretty"
Серверийн хариултанд би индексжүүлсэн баримт бичгийн талбаруудын утгыг тайлбар дээр нэмсэн:
{
"blog" : {
"mappings" : {
"post" : {
"properties" : {
/* "content": "<p>Смешная история про котят<p>", */
"content" : {
"type" : "string"
},
/* "published_at": "2014-09-12T20:44:42+00:00" */
"published_at" : {
"type" : "date",
"format" : "strict_date_optional_time||epoch_millis"
},
/* "tags": ["котята", "смешная история"] */
"tags" : {
"type" : "string"
},
/* "title": "Веселые котята" */
"title" : {
"type" : "string"
}
}
}
}
}
}
ES нь нэг утга болон утгын массивыг ялгадаггүй гэдгийг тэмдэглэх нь зүйтэй. Жишээлбэл, гарчгийн талбар нь зүгээр л гарчгийг агуулж байдаг ба tags талбар нь зураглалд ижил байдлаар дүрслэгдсэн мөртүүдийн массивыг агуулдаг.
Бид дараа нь зураглалын талаар дэлгэрэнгүй ярих болно.
хүсэлтүүд
Баримт бичгийг ID дугаараар нь татаж авч байна:
# извлечем документ с id 1 типа post из индекса blog
curl -XGET "$ES_URL/blog/post/1?pretty"
{
"_index" : "blog",
"_type" : "post",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"title" : "Веселые котята",
"content" : "<p>Смешная история про котят<p>",
"tags" : [ "котята", "смешная история" ],
"published_at" : "2014-09-12T20:44:42+00:00"
}
}
Хариултанд шинэ түлхүүрүүд гарч ирэв: _version
и _source
. Ерөнхийдөө бүх түлхүүрүүд нь эхэлдэг _
албан ёсны гэж ангилдаг.
Түлхүүр үг _version
баримт бичгийн хувилбарыг харуулж байна. Энэ нь өөдрөг түгжих механизм ажиллахад шаардлагатай. Жишээлбэл, бид 1-р хувилбартай баримт бичгийг өөрчлөхийг хүсэж байна. Бид өөрчилсөн баримт бичгээ илгээж, энэ нь 1-р хувилбартай документын засвар гэдгийг харуулж байна. Хэрэв өөр хэн нэгэн 1-р хувилбартай документыг засварлаж, биднээс өмнө өөрчлөлт оруулсан бол ES бидний өөрчлөлтийг хүлээж авахгүй, учир нь Энэ нь баримт бичгийг 2-р хувилбараар хадгалдаг.
Түлхүүр үг _source
Бидний индексжүүлсэн баримт бичгийг агуулна. ES нь хайлтын үйл ажиллагаанд энэ утгыг ашигладаггүй, учир нь Индексийг хайлт хийхэд ашигладаг. Зай хэмнэхийн тулд ES нь шахсан эх баримт бичгийг хадгалдаг. Хэрэв бидэнд эх баримтыг бүхэлд нь биш зөвхөн id хэрэгтэй бол бид эх хадгалах санг идэвхгүй болгож болно.
Хэрэв бидэнд нэмэлт мэдээлэл хэрэггүй бол бид зөвхөн _source-ийн агуулгыг авах боломжтой:
curl -XGET "$ES_URL/blog/post/1/_source?pretty"
{
"title" : "Веселые котята",
"content" : "<p>Смешная история про котят<p>",
"tags" : [ "котята", "смешная история" ],
"published_at" : "2014-09-12T20:44:42+00:00"
}
Та мөн зөвхөн тодорхой талбаруудыг сонгож болно:
# извлечем только поле title
curl -XGET "$ES_URL/blog/post/1?_source=title&pretty"
{
"_index" : "blog",
"_type" : "post",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"title" : "Веселые котята"
}
}
Хэд хэдэн нийтлэлийг индексжүүлж, илүү төвөгтэй асуулга ажиллуулцгаая.
curl -XPUT "$ES_URL/blog/post/2" -d'
{
"title": "Веселые щенки",
"content": "<p>Смешная история про щенков<p>",
"tags": [
"щенки",
"смешная история"
],
"published_at": "2014-08-12T20:44:42+00:00"
}'
curl -XPUT "$ES_URL/blog/post/3" -d'
{
"title": "Как у меня появился котенок",
"content": "<p>Душераздирающая история про бедного котенка с улицы<p>",
"tags": [
"котята"
],
"published_at": "2014-07-21T20:44:42+00:00"
}'
Эрэмбэлж байна
# найдем последний пост по дате публикации и извлечем поля title и published_at
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"size": 1,
"_source": ["title", "published_at"],
"sort": [{"published_at": "desc"}]
}'
{
"took" : 8,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 3,
"max_score" : null,
"hits" : [ {
"_index" : "blog",
"_type" : "post",
"_id" : "1",
"_score" : null,
"_source" : {
"title" : "Веселые котята",
"published_at" : "2014-09-12T20:44:42+00:00"
},
"sort" : [ 1410554682000 ]
} ]
}
}
Бид сүүлчийн бичлэгийг сонгосон. size
олгох баримт бичгийн тоог хязгаарладаг. total
хүсэлттэй тохирох баримт бичгийн нийт тоог харуулна. sort
гаралт нь эрэмбэлэх бүхэл тоонуудын массивыг агуулна. Тэдгээр. огноог бүхэл тоо болгон хөрвүүлсэн. Эрэмбэлэх талаар дэлгэрэнгүй мэдээллийг эндээс авах боломжтой
Шүүлтүүр ба асуулга
ES нь 2-р хувилбараас хойш шүүлтүүр болон асуулга хоёрыг ялгадаггүй
Асуулгын контекст нь шүүлтүүрийн контекстээс ялгаатай бөгөөд асуулга нь _score үүсгэдэг бөгөөд кэшд хадгалагдаагүй болно. Би дараа нь ямар _оноо байгааг харуулах болно.
Огноогоор шүүнэ үү
Бид хүсэлтийг ашигладаг
# получим посты, опубликованные 1ого сентября или позже
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"filter": {
"range": {
"published_at": { "gte": "2014-09-01" }
}
}
}'
Шошгоор шүүх
Бидний хэрэглэдэг
# найдем все документы, в поле tags которых есть элемент 'котята'
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"_source": [
"title",
"tags"
],
"filter": {
"term": {
"tags": "котята"
}
}
}'
{
"took" : 9,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 2,
"max_score" : 1.0,
"hits" : [ {
"_index" : "blog",
"_type" : "post",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"title" : "Веселые котята",
"tags" : [ "котята", "смешная история" ]
}
}, {
"_index" : "blog",
"_type" : "post",
"_id" : "3",
"_score" : 1.0,
"_source" : {
"title" : "Как у меня появился котенок",
"tags" : [ "котята" ]
}
} ]
}
}
Бүрэн текст хайлт
Манай гурван баримт бичиг агуулгын талбарт дараахь зүйлийг агуулна.
<p>Смешная история про котят<p>
<p>Смешная история про щенков<p>
<p>Душераздирающая история про бедного котенка с улицы<p>
Бидний хэрэглэдэг
# source: false означает, что не нужно извлекать _source найденных документов
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"_source": false,
"query": {
"match": {
"content": "история"
}
}
}'
{
"took" : 13,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 3,
"max_score" : 0.11506981,
"hits" : [ {
"_index" : "blog",
"_type" : "post",
"_id" : "2",
"_score" : 0.11506981
}, {
"_index" : "blog",
"_type" : "post",
"_id" : "1",
"_score" : 0.11506981
}, {
"_index" : "blog",
"_type" : "post",
"_id" : "3",
"_score" : 0.095891505
} ]
}
}
Гэсэн хэдий ч, хэрэв бид агуулгын талбараас "түүх" гэж хайвал бид юу ч олохгүй, учир нь Индекс нь зөвхөн эх үгсийг агуулдаг бөгөөд тэдгээрийн иш биш. Өндөр чанартай хайлт хийхийн тулд анализаторыг тохируулах хэрэгтэй.
талбар _score
шоу
Анализаторууд
Анализатор нь нэгээс бүрдэнэ
ES-д хэд хэдэн байдаг
Давуу талыг ашиглацгаая
# используем анализатор standard
# обязательно нужно перекодировать не ASCII символы
curl -XGET "$ES_URL/_analyze?pretty&analyzer=standard&text=%D0%92%D0%B5%D1%81%D0%B5%D0%BB%D1%8B%D0%B5%20%D0%B8%D1%81%D1%82%D0%BE%D1%80%D0%B8%D0%B8%20%D0%BF%D1%80%D0%BE%20%D0%BA%D0%BE%D1%82%D1%8F%D1%82"
{
"tokens" : [ {
"token" : "веселые",
"start_offset" : 0,
"end_offset" : 7,
"type" : "<ALPHANUM>",
"position" : 0
}, {
"token" : "истории",
"start_offset" : 8,
"end_offset" : 15,
"type" : "<ALPHANUM>",
"position" : 1
}, {
"token" : "про",
"start_offset" : 16,
"end_offset" : 19,
"type" : "<ALPHANUM>",
"position" : 2
}, {
"token" : "котят",
"start_offset" : 20,
"end_offset" : 25,
"type" : "<ALPHANUM>",
"position" : 3
} ]
}
# используем анализатор russian
curl -XGET "$ES_URL/_analyze?pretty&analyzer=russian&text=%D0%92%D0%B5%D1%81%D0%B5%D0%BB%D1%8B%D0%B5%20%D0%B8%D1%81%D1%82%D0%BE%D1%80%D0%B8%D0%B8%20%D0%BF%D1%80%D0%BE%20%D0%BA%D0%BE%D1%82%D1%8F%D1%82"
{
"tokens" : [ {
"token" : "весел",
"start_offset" : 0,
"end_offset" : 7,
"type" : "<ALPHANUM>",
"position" : 0
}, {
"token" : "истор",
"start_offset" : 8,
"end_offset" : 15,
"type" : "<ALPHANUM>",
"position" : 1
}, {
"token" : "кот",
"start_offset" : 20,
"end_offset" : 25,
"type" : "<ALPHANUM>",
"position" : 3
} ]
}
Стандарт анализатор нь утсыг зайгаар хувааж, бүх зүйлийг жижиг үсгээр хөрвүүлдэг, орос анализатор нь чухал биш үгсийг арилгаж, жижиг үсгээр хөрвүүлж, үгийн ишийг үлдээдэг.
Оросын анализатор ямар Tokenizer, TokenFilters, CharFilters ашигладаг болохыг харцгаая.
{
"filter": {
"russian_stop": {
"type": "stop",
"stopwords": "_russian_"
},
"russian_keywords": {
"type": "keyword_marker",
"keywords": []
},
"russian_stemmer": {
"type": "stemmer",
"language": "russian"
}
},
"analyzer": {
"russian": {
"tokenizer": "standard",
/* TokenFilters */
"filter": [
"lowercase",
"russian_stop",
"russian_keywords",
"russian_stemmer"
]
/* CharFilters отсутствуют */
}
}
}
html хаягуудыг хайчлах орос хэл дээр үндэслэсэн анализатороо тайлбарлая. Үүнийг анхдагч гэж нэрлэе, учир нь ийм нэртэй анализаторыг анхдагчаар ашиглах болно.
{
"filter": {
"ru_stop": {
"type": "stop",
"stopwords": "_russian_"
},
"ru_stemmer": {
"type": "stemmer",
"language": "russian"
}
},
"analyzer": {
"default": {
/* добавляем удаление html тегов */
"char_filter": ["html_strip"],
"tokenizer": "standard",
"filter": [
"lowercase",
"ru_stop",
"ru_stemmer"
]
}
}
}
Эхлээд бүх HTML хаягууд эх тэмдэгт мөрөөс хасагдах ба дараа нь токенизаторын стандарт үүнийг токен болгон хувааж, үүссэн токенууд нь жижиг үсгээр шилжиж, ач холбогдолгүй үгс хасагдаж, үлдсэн токенууд нь үгийн иш хэвээр үлдэнэ.
Индекс үүсгэх
Дээр бид анхдагч анализаторыг тайлбарласан. Энэ нь бүх мөрийн талбарт хэрэгжинэ. Манай нийтлэлд олон тооны шошго агуулагдаж байгаа тул хаягуудыг мөн анализатор боловсруулна. Учир нь Бид шошготой яг таарч байгаа нийтлэлүүдийг хайж байгаа тул шошгоны талбарт дүн шинжилгээ хийхийг идэвхгүй болгох хэрэгтэй.
Шошго талбарын шинжилгээг идэвхгүй болгосон анализатор, зураглал бүхий индекс блог2 үүсгэцгээе:
curl -XPOST "$ES_URL/blog2" -d'
{
"settings": {
"analysis": {
"filter": {
"ru_stop": {
"type": "stop",
"stopwords": "_russian_"
},
"ru_stemmer": {
"type": "stemmer",
"language": "russian"
}
},
"analyzer": {
"default": {
"char_filter": [
"html_strip"
],
"tokenizer": "standard",
"filter": [
"lowercase",
"ru_stop",
"ru_stemmer"
]
}
}
}
},
"mappings": {
"post": {
"properties": {
"content": {
"type": "string"
},
"published_at": {
"type": "date"
},
"tags": {
"type": "string",
"index": "not_analyzed"
},
"title": {
"type": "string"
}
}
}
}
}'
Энэ индекст (blog3) ижил 2 бичлэгийг оруулъя. Би энэ үйл явцыг орхих болно, учир нь ... Энэ нь блогийн индекст бичиг баримт нэмэхтэй адил юм.
Илэрхийллийн дэмжлэг бүхий бүрэн текст хайлт
Өөр төрлийн хүсэлтийг авч үзье:
# найдем документы, в которых встречается слово 'истории'
# query -> simple_query_string -> query содержит поисковый запрос
# поле title имеет приоритет 3
# поле tags имеет приоритет 2
# поле content имеет приоритет 1
# приоритет используется при ранжировании результатов
curl -XPOST "$ES_URL/blog2/post/_search?pretty" -d'
{
"query": {
"simple_query_string": {
"query": "истории",
"fields": [
"title^3",
"tags^2",
"content"
]
}
}
}'
Учир нь Бид орос хэлтэй анализатор ашиглаж байгаа тул энэ хүсэлт нь зөвхөн "түүх" гэсэн үгийг агуулсан бүх баримт бичгийг буцааж өгөх болно.
Хүсэлт нь тусгай тэмдэгт агуулсан байж болно, жишээлбэл:
""fried eggs" +(eggplant | potato) -frittata"
Хүсэлтийн синтакс:
+ signifies AND operation
| signifies OR operation
- negates a single token
" wraps a number of tokens to signify a phrase for searching
* at the end of a term signifies a prefix query
( and ) signify precedence
~N after a word signifies edit distance (fuzziness)
~N after a phrase signifies slop amount
# найдем документы без слова 'щенки'
curl -XPOST "$ES_URL/blog2/post/_search?pretty" -d'
{
"query": {
"simple_query_string": {
"query": "-щенки",
"fields": [
"title^3",
"tags^2",
"content"
]
}
}
}'
# получим 2 поста про котиков
лавлагаа
Elasctic.co лавлагаа Гарын авлага Тайлбар толь тохиргоо Баримт бичиг боловсруулах Индекс үйл ажиллагаа Хүсэлтийн жагсаалт
PS
Хэрэв та ижил төстэй нийтлэл-хичээл сонирхож байгаа бол, шинэ нийтлэл гаргах санаатай эсвэл хамтран ажиллах санал байвал би хувийн мессеж эсвэл имэйлээр мессеж хүлээн авахдаа баяртай байх болно. [имэйлээр хамгаалагдсан].
Эх сурвалж: www.habr.com