Bunúsacha Elasticsearch

Is inneall cuardaigh é Elasticsearch le json rest api, ag baint úsáide as Lucene agus scríofa i Java. Tá cur síos ar na buntáistí uile a bhaineann leis an inneall seo ar fáil ag láithreán gréasáin oifigiúil. Sa mhéid seo a leanas déanfaimid tagairt do Elasticsearch mar ES.

Úsáidtear innill chomhchosúla le haghaidh cuardaigh chasta i mbunachar sonraí doiciméad. Mar shampla, cuardach ag cur deilbhíocht na teanga san áireamh nó cuardach de réir geo-chomhordanáidí.

San Airteagal seo beidh mé ag caint faoi na bunghnéithe ES ag baint úsáide as an sampla de innéacsú blog post. Taispeánfaidh mé duit conas doiciméid a scagadh, a shórtáil agus a chuardach.

Chun nach mbeidh mé ag brath ar an gcóras oibriúcháin, déanfaidh mé gach iarratas chuig ES ag baint úsáide as CURL. Tá breiseán ann freisin le haghaidh google chrome ar a dtugtar ciall.

Tá naisc le doiciméadú agus foinsí eile sa téacs. Ag an deireadh tá naisc chun rochtain thapa a fháil ar na doiciméid. Is féidir sainmhínithe ar théarmaí neamhaithnidiúla a fháil i gluais.

Suiteáil ES

Chun seo a dhéanamh, ní mór dúinn Java ar dtús. Forbróirí a mholadh shuiteáil leaganacha Java níos nuaí ná Java 8 update 20 nó Java 7 update 55.

Tá an dáileadh ES ar fáil ag suíomh forbróra. Tar éis duit an chartlann a dhíphacáil ní mór duit a rith bin/elasticsearch. Ar fáil freisin pacáistí le haghaidh apt agus yum. Tá íomhá oifigiúil do docker. Tuilleadh faoi shuiteáil.

Tar éis a shuiteáil agus a sheoladh, déanaimis seiceáil ar an bhfeidhmiúlacht:

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

curl -X GET $ES_URL

Gheobhaidh muid rud mar 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"
}

Innéacsú

Cuirimis postáil le 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"
}'

freagra freastalaí:

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

ES cruthaithe go huathoibríoch innéacs blag agus Cineál post. Is féidir linn analaí coinníollach a tharraingt: is bunachar sonraí é innéacs, agus is tábla é cineál sa bhunachar sonraí seo. Tá a scéim féin ag gach cineál − mapáil, díreach cosúil le tábla coibhneasta. Gintear mapáil go huathoibríoch nuair a bhíonn an doiciméad innéacsaithe:

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

I bhfreagra an fhreastalaí, chuir mé luachanna réimsí an doiciméid innéacsaithe leis sna tuairimí:

{
  "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 fiú a thabhairt faoi deara nach ndéanann ES idirdhealú idir luach aonair agus raon luachanna. Mar shampla, níl sa réimse teidil ach teideal, agus tá sraith teaghráin i réimse na gclibeanna, cé go léirítear iad ar an mbealach céanna sa mhapáil.
Labhróimid níos mó faoi mhapáil níos déanaí.

Iarratais

Cáipéis a aisghabháil trína haitheantas:

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

Léiríodh eochracha nua sa fhreagra: _version и _source. Go ginearálta, gach eochair ag tosú le _ rangaithe mar oifigiúil.

Eochair _version léiríonn an leagan doiciméad. Tá sé ag teastáil le go n-oibreoidh an mheicníocht glasála dóchasach. Mar shampla, ba mhaith linn doiciméad a bhfuil leagan 1 aige a athrú. Cuirimid an doiciméad athraithe isteach agus cuirimid in iúl gur eagarthóireacht é seo ar dhoiciméad le leagan 1. Má chuir duine éigin eile doiciméad le leagan 1 in eagar freisin agus má chuir siad athruithe isteach romhainn, ansin Ní ghlacfaidh ES lenár n-athruithe, mar gheall ar stórálann sé an doiciméad le leagan 2.

Eochair _source ina bhfuil an doiciméad a innéacsú againn. Ní úsáideann ES an luach seo le haghaidh oibríochtaí cuardaigh toisc Úsáidtear innéacsanna chun cuardach a dhéanamh. Chun spás a shábháil, stórálann ES doiciméad foinse comhbhrúite. Mura dteastaíonn uainn ach an t-aitheantas, agus ní an doiciméad foinse iomlán, is féidir linn an stór foinse a dhíchumasú.

Mura bhfuil eolas breise ag teastáil uainn, ní féidir linn a fháil ach a bhfuil in _ foinse:

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

Ní féidir leat ach réimsí áirithe a roghnú freisin:

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

Déanaimis cúpla post eile a innéacsú agus fiosruithe níos casta a rith.

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

Sórtáil

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

Roghnaigh muid an post deireanach. size teorainn le líon na ndoiciméad atá le heisiúint. total léiríonn sé líon iomlán na ndoiciméad atá ag teacht leis an iarratas. sort san aschur tá sraith slánuimhreacha trína ndéantar sórtáil. Iad siúd. aistríodh an dáta go slánuimhir. Is féidir tuilleadh eolais a fháil faoin sórtáil i doiciméadú.

Scagairí agus fiosruithe

ES toisc nach ndéanann leagan 2 idirdhealú idir scagairí agus fiosruithe, ina ionad sin tugtar isteach coincheap na gcomhthéacsanna.
Tá difríocht idir comhthéacs ceiste agus comhthéacs scagaire sa mhéid is go ngineann an cheist scór _scór agus nach bhfuil sé i dtaisce. Taispeánfaidh mé duit cad é _score níos déanaí.

Фильтрация по дате

Bainimid úsáid as an iarratas raon i gcomhthéacs an scagaire:

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

Scag le clibeanna

úsáidimid ceist téarma chun aitheantas doiciméad a chuardach ina bhfuil focal ar leith:

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

Cuardach téacs iomlán

Tá na nithe seo a leanas i réimse an ábhair i dtrí cinn dár ndoiciméid:

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

úsáidimid ceist mheaitseáil chun aitheantas doiciméad a chuardach ina bhfuil focal ar leith:

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

Mar sin féin, má chuardaíonn muid “scéalta” i réimse an ábhair, ní bhfaighidh muid rud ar bith, mar gheall ar Níl san innéacs ach na bunfhocail, ní a gcuid gais. Chun cuardach ardcháilíochta a dhéanamh, ní mór duit an anailísí a chumrú.

Réimse _score seónna ábharthacht. Má dhéantar an t-iarratas i gcomhthéacs scagaire, beidh an luach _score cothrom le 1 i gcónaí, rud a chiallaíonn go bhfuil meaitseáil iomlán leis an scagaire.

Anailíseoirí

Anailíseoirí ag teastáil chun an buntéacs a thiontú ina shraith comharthaí.
Anailíseoirí comhdhéanta de cheann amháin Tokenizer agus roinnt roghnach TokenFilters. Féadfaidh roinnt mhaith a bheith roimh Tokenizer Scagairí Char. Briseann comharthaitheoirí an teaghrán foinse ina comharthaí, mar spásanna agus carachtair phoncaíochta. Is féidir le TokenFilter comharthaí a athrú, cinn nua a scriosadh nó a chur leis, mar shampla, gan ach gas an fhocail a fhágáil, réamhfhocail a bhaint, comhchiallaigh a chur leis. CharFilter - athraíonn an teaghrán foinse iomlán, mar shampla, gearrann sé amach clibeanna html.

Tá roinnt mhaith ag ES anailíseoirí caighdeánacha. Mar shampla, anailíseoir Rúisis.

A ligean ar leas a bhaint as API agus féachaimis conas a athraíonn na hanailíseoirí caighdeánacha agus na Rúise an teaghrán “Scéalta greannmhar faoi kittens”:

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

Scoilt an t-anailíseoir caighdeánach an sreang le spásanna agus d'iompaigh sé gach rud go cás íochtair, bhain an anailísí Rúisis focail nach raibh tábhacht leo, d'athraigh sé go cás íochtair é agus d'fhág sé gas na bhfocal.

Feicfimid cé acu Tokenizer, TokenFilters, CharFilters a úsáideann an anailísí Rúisise:

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

Déanaimis cur síos ar ár n-anailíseoir bunaithe ar Rúisis, a ghearrfaidh amach clibeanna html. A ligean ar glaoch sé réamhshocraithe, mar gheall ar úsáidfear anailísí leis an ainm seo de réir réamhshocraithe.

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

Ar dtús, bainfear na clibeanna HTML go léir as an sreang foinse, ansin roinntear an caighdeán tokenizer ina chomharthaí, aistreofar na comharthaí mar thoradh air go cás íochtair, bainfear focail neamhshuntasach, agus fanfaidh na comharthaí atá fágtha mar ghas an fhocail.

Innéacs a Chruthú

Thuas rinneamar cur síos ar an anailíseoir réamhshocraithe. Bainfidh sé le gach réimse teaghrán. Tá raon clibeanna inár bpostáil, mar sin déanfaidh an anailísí na clibeanna a phróiseáil freisin. Mar Táimid ag lorg postanna de réir meaitseála beacht le clib, ansin ní mór dúinn anailís a dhéanamh ar réimse na gclibeanna a dhíchumasú.

Cruthaímid blag innéacs2 le hanailíseoir agus mapáil, ina bhfuil an anailís ar an réimse clibeanna díchumasaithe:

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

Cuirimis na 3 phost céanna leis an innéacs seo (blog2). Fágfaidh mé an próiseas seo ar lár mar... tá sé cosúil le doiciméid a chur leis an innéacs blag.

Cuardach téacs iomlán le tacaíocht slonn

Breathnaímid ar chineál eile iarratais:

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

Mar Táimid ag baint úsáide as anailíseoir le eascairt na Rúise, ansin seolfar an t-iarratas seo ar ais na doiciméid go léir, cé go bhfuil iontu ach an focal 'stair'.

Féadfaidh carachtair speisialta a bheith san iarratas, mar shampla:

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

Comhréir iarratais:

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

tagairtí

PS

Má tá suim agat in ailt-ceachtanna comhchosúla, má tá smaointe agat le haghaidh ailt nua, nó má tá tograí comhair agat, beidh áthas orm teachtaireacht a fháil i dteachtaireacht phearsanta nó trí ríomhphost [ríomhphost faoi chosaint].

Foinse: will.com