Elasticsearch nyaéta mesin pencari sareng JSON REST API, nganggo Lucene sareng ditulis dina Java. Pedaran ngeunaan sagala kauntungan tina mesin ieu sadia dina Ti ayeuna, urang bakal ngarujuk kana Elasticsearch salaku ES.
Mesin sapertos kitu dianggo pikeun milarian pangkalan data dokumén anu rumit, sapertos milarian dumasar kana morfologi basa atanapi milarian ku koordinat geografis.
Dina tulisan ieu, kuring bakal nutupan dasar-dasar ES nganggo conto ngindeks tulisan blog. Kuring bakal nunjukkeun anjeun kumaha nyaring, nyortir, sareng milarian dokumén.
Pikeun mandiri tina sistem operasi, kuring bakal ngajantenkeun sadaya pamundut ES kuring nganggo CURL. Aya ogé plugin pikeun Google Chrome disebut .
Tumbu ka dokuméntasi jeung sumber séjén disadiakeun sapanjang téks. Tumbu aksés gancang kana dokuméntasi disadiakeun di ahir. Watesan istilah anu teu biasa tiasa dipendakan dina .
Masang ES
Pikeun ieu urang peryogi Java. Pamekar Pasang vérsi Java anu langkung énggal tibatan Java 8 update 20 atanapi Java 7 update 55.
Distribusi ES sayogi di Saatos unpacking arsip, Anjeun kudu ngajalankeun bin/elasticsearch. Ogé sadia . aya . .
Saatos instalasi sareng peluncuran, hayu urang pariksa pungsionalitasna:
# для удобства запомним адрес в переменную
#export ES_URL=$(docker-machine ip dev):9200
export ES_URL=localhost:9200
curl -X GET $ES_URLKami bakal nampi réspon sapertos kieu:
{
"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"
}Indexing
Hayu urang tambahkeun pos ka 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"
}'
respon server:
{
"_index" : "blog",
"_type" : "post",
"_id" : "1",
"_version" : 1,
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"created" : false
}
ES otomatis dijieun blog jeung pos. Analogi kasar tiasa digambar: indéks mangrupikeun pangkalan data, sareng jinis mangrupikeun méja dina pangkalan data éta. Unggal tipe boga skéma sorangan- , kawas tabel relational. Pemetaan dihasilkeun sacara otomatis nalika dokumén diindeks:
# Получим mapping всех типов индекса blog
curl -XGET "$ES_URL/blog/_mapping?pretty"Dina réspon server, kuring nambihan nilai lapangan tina dokumén anu diindeks dina koméntar:
{
"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"
}
}
}
}
}
}Perlu dicatet yén ES henteu ngabédakeun antara nilai tunggal sareng sakumpulan nilai. Contona, widang judul ngandung ngan hiji judul, sedengkeun widang tag ngandung hiji Asép Sunandar Sunarya ti string, sanajan aranjeunna digambarkeun idéntik dina pemetaan.
Urang bakal ngobrol ngeunaan pemetaan dina leuwih jéntré engké.
Paménta
Extracting dokumén ku ID na:
# извлечем документ с 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"
}
}Konci anyar muncul dina réspon: _version и _sourceSacara umum, sadaya konci anu dimimitian ku _ digolongkeun kana barang jasa.
konci _version Némbongkeun versi dokumén. Ieu diperlukeun pikeun mékanisme konci optimistis jalan. Salaku conto, urang hoyong ngarobih dokumén kalayan versi 1. Urang ngalebetkeun dokumén anu dirobih sareng nunjukkeun yén ieu mangrupikeun révisi kana dokumén anu nganggo versi 1. Upami batur ogé ngédit dokumén kalayan versi 1 sareng ngalebetkeun perobahan sateuacan urang, ES moal nampi parobihan kami, sabab éta nyimpen dokumen sareng versi 2.
konci _source Ngandung dokumén anu kami indéks. ES henteu nganggo nilai ieu pikeun operasi milarian, sabab indéks dianggo pikeun milarian. Pikeun ngahemat rohangan, ES nyimpen versi anu dikomprés tina dokumén asli. Upami urang ngan ukur peryogi KTP sareng henteu sadayana dokumen asli, urang tiasa nganonaktipkeun nyimpen anu asli.
Upami urang henteu peryogi inpormasi tambahan, urang ngan ukur tiasa nampi eusi _source:
curl -XGET "$ES_URL/blog/post/1/_source?pretty"{
"title" : "Веселые котята",
"content" : "<p>Смешная история про котят<p>",
"tags" : [ "котята", "смешная история" ],
"published_at" : "2014-09-12T20:44:42+00:00"
}
Anjeun oge bisa milih ukur widang nu tangtu:
# извлечем только поле title
curl -XGET "$ES_URL/blog/post/1?_source=title&pretty"{
"_index" : "blog",
"_type" : "post",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"title" : "Веселые котята"
}
}Hayu urang indéks sababaraha tulisan deui jeung ngajalankeun queries leuwih kompleks.
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"
}'Urut
# найдем последний пост по дате публикации и извлечем поля 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 ]
} ]
}
}Kami geus milih pos panungtungan. size ngawatesan jumlah dokumén anu dikaluarkeun. total nembongkeun jumlah total dokumén cocog query. sort Kaluaran ngandung sajumlah integer anu diurutkeun. Hartina, tanggal geus dirobah jadi integer. Inpo nu langkung lengkep ihwal asihan tiasa dipendakan dina .
Saringan sareng patarosan
ES saprak versi 2 teu ngabedakeun antara saringan jeung queries, gantina .
Kontéks query bénten sareng kontéks saringan dina éta query ngahasilkeun _score sareng henteu sindangan. Kuring bakal ngajelaskeun naon _score engké.
Nyaring dumasar titimangsa
Ngagunakeun query dina konteks saringan:
# получим посты, опубликованные 1ого сентября или позже
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"filter": {
"range": {
"published_at": { "gte": "2014-09-01" }
}
}
}'Nyaring ku tag
Urang make Pikeun milarian ID dokumén anu ngandung kecap anu dipasihkeun:
# найдем все документы, в поле 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" : [ "котята" ]
}
} ]
}
}Pilarian téks lengkep
Tilu dokumén kami ngandung ieu dina widang eusi:
<p>Смешная история про котят<p><p>Смешная история про щенков<p><p>Душераздирающая история про бедного котенка с улицы<p>
Urang make Pikeun milarian ID dokumén anu ngandung kecap anu dipasihkeun:
# 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
} ]
}
}Nanging, upami urang milarian "carita" dina widang eusi, urang moal mendakan nanaon, sabab indéksna ngan ukur ngandung kecap asli, sanés batangna. Pikeun ngalaksanakeun pamilarian kualitas, urang kedah ngonpigurasikeun analisa.
médan _score nunjukkeun Lamun query ieu dieksekusi dina konteks filter, nilai _score bakal salawasna jadi 1, nu hartina filter nu geus pinuh loyog.
Analis
diperlukeun pikeun transformasi téks sumber kana sakumpulan tokens.
Analis diwangun ku hiji sareng sababaraha pilihan Tokenizer tiasa miheulaan sababaraha Tokenizers megatkeun string sumber kana tokens, contona, ku spasi jeung karakter tanda baca. TokenFilters tiasa ngarobih token, ngahapus, atanapi nambihan anu énggal, contona, ngan ukur nyésakeun kecap batang, ngaleungitkeun preposisi, atanapi nambihan sinonim. CharFilters ngaropéa string sumber sagemblengna, contona, ku stripping tag HTML.
Aya sababaraha di ES Contona, hiji analyzer .
Hayu urang mangpaatkeun Sareng hayu urang tingali kumaha standar sareng parser Rusia ngarobih senar "Carita lucu ngeunaan anak ucing":
# используем анализатор 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
} ]
}Analis standar ngabagi string dina spasi tur ngarobah sagalana kana hurup leutik, analisa Rusia dihapus kecap teu penting, dirobah jadi hurup leutik, sarta ninggalkeun kecap batang.
Hayu urang tingali Tokenizer, TokenFilters, sareng CharFilters anu dianggo ku analisa Rusia:
{
"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 отсутствуют */
}
}
}Hayu urang ngajelaskeun analisa basis Rusia urang sorangan anu bakal ngaleungitkeun tag HTML. Kami bakal nyebatna standar, sabab nami ieu bakal dianggo sacara standar.
{
"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"
]
}
}
}Mimiti, sadaya tag HTML bakal dipiceun tina senar sumber, teras éta bakal dibagi kana token ku standar tokenizer, token anu dihasilkeun bakal dirobih kana hurup leutik, kecap anu teu penting bakal dipupus, sareng token sésana bakal janten kecap bobot.
Nyiptakeun indéks
Di luhur, kami ngajelaskeun analisa standar. Ieu bakal dilarapkeun ka sadaya widang string. Pos kami ngandung sababaraha tag, ku kituna tag ogé bakal diolah ku analisa. Kusabab urang milarian tulisan anu cocog sareng tag anu pasti, urang kedah nganonaktipkeun analisa pikeun widang "tag".
Hayu urang ngadamel indéks blog2 nganggo analisa sareng pemetaan, dimana analisa kolom tag dinonaktipkeun:
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"
}
}
}
}
}'Hayu urang tambahkeun tilu tulisan anu sami kana indéks ieu (blog2). Kuring bakal ngalangkungan prosés ieu, sabab éta sami sareng nambihan dokumén kana indéks blog.
Pilarian téks lengkep sareng dukungan éksprési
Hayu urang kenal sareng jinis patarosan anu sanés:
# найдем документы, в которых встречается слово 'истории'
# 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"
]
}
}
}'Kusabab kami nganggo analisa nganggo stemming Rusia, pamundut ieu bakal ngabalikeun sadaya dokumén, sanaos ngan ukur ngandung kecap 'sajarah'.
Patarosan tiasa ngandung karakter khusus, contona:
""fried eggs" +(eggplant | potato) -frittata"Sintaksis pamundut:
+ 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 поста про котиковrujukan
PS
Upami anjeun resep kana artikel tutorial anu sami, gaduh ide pikeun tulisan énggal, atanapi gaduh saran kolaborasi, kuring bakal resep ngadangu ti anjeun ngalangkungan pesen pribadi atanapi email di m.kuzmin+habr@darkleaf.ru.
sumber: www.habr.com
