Bun-bheachdan Elasticsearch

’S e einnsean sgrùdaidh le JSON REST API a th’ ann an Elasticsearch, a’ cleachdadh Lucene agus sgrìobhte ann an Java. Gheibhear tuairisgeul air buannachdan an einnsean seo aig làrach-lìn oifigeilBho seo a-mach, bidh sinn a’ toirt iomradh air Elasticsearch mar ES.

Bithear a’ cleachdadh einnseanan mar seo airson rannsachaidhean stòr-dàta sgrìobhainnean iom-fhillte, leithid rannsachadh stèidhichte air morf-eòlas cànain no rannsachadh a rèir co-chomharran cruinn-eòlasach.

San artaigil seo, còmhdaichidh mi bunaitean ES a’ cleachdadh eisimpleir clàr-amais phuist bhlog. Seallaidh mi dhut mar a nì thu sìoladh, seòrsachadh agus rannsachadh air sgrìobhainnean.

Gus a bhith neo-eisimeileach bhon t-siostam obrachaidh, bidh mi a’ dèanamh a h-uile iarrtas ES agam le bhith a’ cleachdadh CURL. Tha plugan ann cuideachd airson Google Chrome air a bheil mothachadh.

Tha ceanglaichean gu sgrìobhainnean agus stòran eile air an toirt seachad air feadh an teacsa. Tha ceanglaichean luath gu sgrìobhainnean air an toirt seachad aig a’ cheann thall. Gheibhear mìneachaidhean air teirmean nach eil thu eòlach orra ann an briathrachasan.

A’ stàladh ES

Airson seo feumaidh sinn Java an toiseach. Luchd-leasachaidh moladh Stàlaich dreachan Java nas ùire na Java 8 ùrachadh 20 no Java 7 ùrachadh 55.

Tha an sgaoileadh ES ri fhaighinn air làrach leasaicheÀs dèidh dhut an tasglann a dhì-phacadh, feumaidh tu ruith bin/elasticsearchRi fhaighinn cuideachd pacaidean airson apt agus yum. Tha ìomhaigh oifigeil airson Docker. Tuilleadh mu stàladh.

Às dèidh an stàlaidh agus an cur air bhog, leig dhuinn sùil a thoirt air a’ ghnìomhachd:

# для удобства запомним адрес в переменную
#export ES_URL=$(docker-machine ip dev):9200
export ES_URL=localhost:9200

curl -X GET $ES_URL

Gheibh sinn freagairt a tha coltach ri seo:

{
  "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

Cuiridh sinn post ri 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"
}'

freagairt an fhrithealaiche:

{
  "_index" : "blog",
  "_type" : "post",
  "_id" : "1",
  "_version" : 1,
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "created" : false
}

ES air a chruthachadh gu fèin-ghluasadach clàr-amais blog agus seòrsa de post. Faodar coimeas garbh a tharraing: is e stòr-dàta a th’ ann an clàr-amais, agus is e clàr taobh a-staigh an stòr-dàta sin a th’ ann an seòrsa. Tha sgeama fhèin aig gach seòrsa— mapadh, dìreach mar chlàr dàimheil. Thèid mapadh a chruthachadh gu fèin-ghluasadach nuair a thèid clàr-amais a chur air sgrìobhainn:

# Получим mapping всех типов индекса blog
curl -XGET "$ES_URL/blog/_mapping?pretty"

Anns an fhreagairt frithealaiche, chuir mi luachan achaidh an sgrìobhainn clàr-amais ris na beachdan:

{
  "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"
          }
        }
      }
    }
  }
}

Is fhiach a thoirt fa-near nach eil ES a’ dèanamh eadar-dhealachadh eadar aon luach agus sreath de luachan. Mar eisimpleir, chan eil anns an raon tiotal ach tiotal, agus anns an raon tagaichean tha sreath de shreangan, eadhon ged a tha iad air an riochdachadh san aon dòigh sa mhapadh.
Bruidhnidh sinn mu dheidhinn mapadh nas mionaidiche nas fhaide air adhart.

Iarrtasan

A’ toirt a-mach sgrìobhainn leis an ID aige:

# извлечем документ с 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"
  }
}

Nochd iuchraichean ùra san fhreagairt: _version и _sourceSan fharsaingeachd, a h-uile iuchair a thòisicheas le _ air an seòrsachadh mar nithean seirbheis.

Prìomh _version A’ sealltainn dreach na sgrìobhainn. Tha seo riatanach airson gum bi an dòigh-ghlasaidh dòchasach ag obair. Mar eisimpleir, tha sinn airson sgrìobhainn atharrachadh le dreach 1. Cuiridh sinn a-steach an sgrìobhainn atharraichte agus comharraichidh sinn gur e seo ath-sgrùdadh air an sgrìobhainn le dreach 1. Ma dheasaich cuideigin eile an sgrìobhainn le dreach 1 cuideachd agus ma chuir iad na h-atharrachaidhean a-steach romhainn, cha ghabh ES ris na h-atharrachaidhean againn, leis gu bheil e a’ stòradh na sgrìobhainn le dreach 2.

Prìomh _source Anns a bheil an sgrìobhainn a chuir sinn ann an clàr-amais. Chan eil ES a’ cleachdadh an luach seo airson obrachaidhean rannsachaidh, oir is e clàran-amais a thathas a’ cleachdadh airson rannsachadh. Gus àite a shàbhaladh, bidh ES a’ stòradh dreach teannaichte den sgrìobhainn thùsail. Mura h-eil feum againn ach air an ID agus chan e an sgrìobhainn thùsail gu lèir, is urrainn dhuinn casg a chuir air stòradh an sgrìobhainn thùsail.

Mura h-eil feum againn air fiosrachadh a bharrachd, is urrainn dhuinn dìreach susbaint _source fhaighinn:

curl -XGET "$ES_URL/blog/post/1/_source?pretty"
{
  "title" : "Веселые котята",
  "content" : "<p>Смешная история про котят<p>",
  "tags" : [ "котята", "смешная история" ],
  "published_at" : "2014-09-12T20:44:42+00:00"
}

Faodaidh tu cuideachd raointean sònraichte a thaghadh a-mhàin:

# извлечем только поле title
curl -XGET "$ES_URL/blog/post/1?_source=title&pretty"
{
  "_index" : "blog",
  "_type" : "post",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "_source" : {
    "title" : "Веселые котята"
  }
}

Feuchaidh sinn ri beagan a bharrachd phuist a chlàr-amais agus ceistean nas iom-fhillte a ruith.

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"
}'

Deasachadh

# найдем последний пост по дате публикации и извлечем поля 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 ]
    } ]
  }
}

Tha sinn air an dreuchd mu dheireadh a thaghadh. size a’ cuingealachadh an àireamh de sgrìobhainnean a thèid a thoirt seachad. total a’ sealltainn an àireamh iomlan de sgrìobhainnean a tha a’ freagairt ris a’ cheist. sort Tha sreath de dh’àireamhan slàn anns an toradh leis a bheil an seòrsachadh ga dhèanamh. ’S e sin, chaidh an ceann-latha atharrachadh gu àireamh slàn. Gheibhear barrachd fiosrachaidh mu sheòrsachadh ann an sgrìobhainnean.

Criathragan agus ceistean

Chan eil ES bho dhreach 2 a’ dèanamh eadar-dhealachadh eadar sìoltachain agus ceistean, an àite sin tha bun-bheachd nan co-theacsan air a thoirt a-steach.
Tha co-theacsa na ceiste eadar-dhealaichte bhon cho-theacsa sìoltachain leis gu bheil an ceist a’ gineadh _sgòr agus nach eil i air a stòradh san tasgadan. Mìnichidh mi dè a th’ ann an _sgòr nas fhaide air adhart.

Criathraich a rèir ceann-latha

A’ cleachdadh a’ cheiste raon ann an co-theacsa an criathrag:

# получим посты, опубликованные 1ого сентября или позже
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
  "filter": {
    "range": {
      "published_at": { "gte": "2014-09-01" }
    }
  }
}'

Criathraich le tagaichean

Cleachd ceist teirm Gus IDan sgrìobhainnean anns a bheil facal sònraichte a lorg:

# найдем все документы, в поле 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" : [ "котята" ]
      }
    } ]
  }
}

Rannsachadh teacsa slàn

Tha na leanas anns na trì sgrìobhainnean againn anns an raon susbaint:

  • <p>Смешная история про котят<p>
  • <p>Смешная история про щенков<p>
  • <p>Душераздирающая история про бедного котенка с улицы<p>

Cleachd ceist maidsidh Gus IDan sgrìobhainnean anns a bheil facal sònraichte a lorg:

# 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
    } ]
  }
}

Ach, ma nì sinn rannsachadh airson “sgeulachdan” anns an raon susbaint, cha lorg sinn dad, oir chan eil anns a’ chlàr-amais ach faclan tùsail, chan e na freumhaichean aca. Gus rannsachadh càileachd a dhèanamh, feumaidh sinn an inneal-anailis a rèiteachadh.

achadh _score taisbeanaidhean buntainneachdMa thèid an ceist a chur an gnìomh ann an co-theacsa criathrag, bidh an luach _score an-còmhnaidh co-ionann ri 1, agus tha sin a’ ciallachadh gu bheil an criathrag air a mhaidseadh gu h-iomlan.

Luchd-anailis

Luchd-anailis a tha a dhìth gus an teacsa tùsail a thionndadh gu seata de chomharran.
Tha na h-anailisichean air an dèanamh suas de aon Tokenizer agus grunn roghainnean Criathragan ComharranDh’fhaodadh gum bi grunn chomharran ann roimhe Criathragan-charactaranBidh Tokenizers a’ briseadh sreang tùsail ann an comharran, mar eisimpleir, le beàrnan agus caractaran puingeachaidh. Faodaidh TokenFilters comharran atharrachadh, an toirt air falbh, no feadhainn ùra a chur ris, mar eisimpleir, le bhith a’ fàgail dìreach bun an fhacail, a’ toirt air falbh roimhearan, no a’ cur co-fhaclan ris. Bidh CharFilters ag atharrachadh an t-sreang tùsail gu tur, mar eisimpleir, le bhith a’ toirt air falbh tagaichean HTML.

Tha grunn ann an ES innealan-anailis àbhaisteachMar eisimpleir, anailisiche Russian.

Gabhamaid brath api agus chì sinn mar a bhios na parsairean àbhaisteach agus Ruiseanach ag atharrachadh an t-sreang "Sgeulachdan èibhinn mu phiseagan":

# используем анализатор 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
  } ]
}

Sgoilt an anailisiche àbhaisteach an sreang aig beàrnan agus thionndaidh e a h-uile càil gu litrichean beaga, thug an anailisiche Ruiseanach air falbh faclan neo-chudromach, thionndaidh e iad gu litrichean beaga, agus dh’fhàg e gasan nam faclan.

Seallaidh sinn dè na Tokenizer, TokenFilters, agus CharFilters a bhios an anailisiche Ruiseanach a’ cleachdadh:

{
  "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 отсутствуют */
    }
  }
}

Leig dhuinn cunntas a thoirt air an anailisiche againn fhèin stèidhichte san Ruis a bhios a’ toirt air falbh tagaichean HTML. Canaidh sinn “default” ris, oir is e seo an anailisiche bunaiteach.

{
  "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"
      ]
    }
  }
}

An toiseach, thèid na tagaichean HTML uile a thoirt air falbh bhon t-sreang thùsail, an uairsin thèid a roinn ann an comharran leis an inbhe tokenizer, thèid na comharran a thig às a thionndadh gu litrichean beaga, thèid faclan neo-chudromach a thoirt air falbh, agus bidh na comharran a tha air fhàgail mar thùs an fhacail.

A’ cruthachadh clàr-amais

Gu h-àrd, mhìnich sinn an inneal-anailis bunaiteach. Thèid a chur an sàs anns a h-uile raon sreang. Tha sreath de thagaichean anns a’ phost againn, agus mar sin thèid na tagaichean a phròiseasadh leis an inneal-anailis cuideachd. Leis gu bheil sinn a’ lorg phuist a tha a’ freagairt ris an taga cheart, feumaidh sinn anailis a dhì-cheadachadh airson an raoin “tagaichean”.

Cruthaichidh sinn clàr-amais blog2 le anailisiche agus mapadh, anns a bheil anailis air an raon tagaichean air a dhì-chomasachadh:

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"
        }
      }
    }
  }
}'

Cuiridh sinn na trì puist cheudna ris a’ chlàr-amais seo (blog2). Leigidh mi seachad a’ phròiseas seo, oir tha e coltach ri bhith a’ cur sgrìobhainnean ris a’ chlàr-amais bhlog.

Rannsachadh làn-theacsa le taic abairtean

Feuchaidh sinn ri seòrsa eile de cheist a thuigsinn:

# найдем документы, в которых встречается слово 'истории'
# 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"
      ]
    }
  }
}'

Leis gu bheil sinn a’ cleachdadh inneal-anailis le freumhan Ruiseanach, tillidh an t-iarrtas seo a h-uile sgrìobhainn, eadhon ged nach eil annta ach am facal ‘eachdraidh’.

Dh’fhaodadh caractaran sònraichte a bhith anns a’ cheist, mar eisimpleir:

""fried eggs" +(eggplant | potato) -frittata"

Co-chàradh ceiste:

+ 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 поста про котиков

iomraidhean

PS

Ma tha ùidh agad ann an artaigilean oideachaidh coltach ris, ma tha beachdan agad airson artaigilean ùra, no ma tha molaidhean sam bith agad airson co-obrachadh, bhithinn toilichte cluinntinn bhuat tro theachdaireachd phrìobhaideach no post-d aig m.kuzmin+habr@darkleaf.ru.

Source: www.habr.com