Hanfodion Elasticsearch

Mae Elasticsearch yn beiriant chwilio gyda json rest api, yn defnyddio Lucene ac wedi'i ysgrifennu yn Java. Mae disgrifiad o holl fanteision yr injan hon ar gael yn gwefan swyddogol. Yn yr hyn sy'n dilyn byddwn yn cyfeirio at Elasticsearch fel ES.

Defnyddir peiriannau tebyg ar gyfer chwiliadau cymhleth mewn cronfa ddata o ddogfennau. Er enghraifft, chwilio gan gymryd i ystyriaeth morffoleg yr iaith neu chwilio yn ôl cyfesurynnau geo.

Yn yr erthygl hon byddaf yn siarad am hanfodion ES gan ddefnyddio'r enghraifft o fynegeio postiadau blog. Byddaf yn dangos i chi sut i hidlo, didoli a chwilio dogfennau.

Er mwyn peidio â dibynnu ar y system weithredu, byddaf yn gwneud pob cais i ES gan ddefnyddio CURL. Mae yna hefyd ategyn ar gyfer google chrome o'r enw synnwyr.

Mae'r testun yn cynnwys dolenni i ddogfennaeth a ffynonellau eraill. Ar y diwedd mae dolenni ar gyfer mynediad cyflym i'r ddogfennaeth. Gellir dod o hyd i ddiffiniadau o dermau anghyfarwydd yn geirfaoedd.

Gosod ES

I wneud hyn, mae angen Java arnom yn gyntaf. Datblygwyr argymell gosod fersiynau Java newyddach na Java 8 update 20 neu Java 7 update 55.

Mae'r dosbarthiad ES ar gael yn safle datblygwr. Ar ôl dadbacio'r archif mae angen i chi redeg bin/elasticsearch. Ar gael hefyd pecynnau ar gyfer apt a yum. Mae yna delwedd swyddogol ar gyfer docwr. Mwy am osod.

Ar ôl gosod a lansio, gadewch i ni wirio'r ymarferoldeb:

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

curl -X GET $ES_URL

Byddwn yn derbyn rhywbeth fel hyn:

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

Mynegeio

Gadewch i ni ychwanegu post at 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"
}'

ymateb gweinydd:

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

ES wedi'i greu'n awtomatig mynegai blog a math post. Gallwn lunio cyfatebiaeth amodol: cronfa ddata yw mynegai, a math yw tabl yn y gronfa ddata hon. Mae gan bob math ei gynllun ei hun − mapio, yn union fel tabl perthynol. Cynhyrchir mapio yn awtomatig pan fydd y ddogfen yn cael ei mynegeio:

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

Yn ymateb y gweinydd, ychwanegais werthoedd meysydd y ddogfen fynegeiedig yn y sylwadau:

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

Mae'n werth nodi nad yw ES yn gwahaniaethu rhwng un gwerth ac amrywiaeth o werthoedd. Er enghraifft, mae'r maes teitl yn syml yn cynnwys teitl, ac mae'r maes tagiau yn cynnwys amrywiaeth o linynnau, er eu bod yn cael eu cynrychioli yn yr un modd wrth fapio.
Byddwn yn siarad mwy am fapio yn nes ymlaen.

Ceisiadau

Adalw dogfen trwy ei 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"
  }
}

Ymddangosodd allweddi newydd yn yr ymateb: _version и _source. Yn gyffredinol, mae pob allwedd yn dechrau gyda _ yn cael eu dosbarthu fel swyddogol.

Allwedd _version yn dangos fersiwn y ddogfen. Mae ei angen er mwyn i'r mecanwaith cloi optimistaidd weithio. Er enghraifft, rydym am newid dogfen sydd â fersiwn 1. Rydym yn cyflwyno'r ddogfen wedi'i newid ac yn nodi mai golygiad o ddogfen gyda fersiwn 1 yw hon. Os yw rhywun arall hefyd wedi golygu dogfen gyda fersiwn 1 ac wedi cyflwyno newidiadau o'n blaenau, yna Ni fydd ES yn derbyn ein newidiadau, oherwydd mae'n storio'r ddogfen gyda fersiwn 2.

Allwedd _source yn cynnwys y ddogfen a fynegwyd gennym. Nid yw ES yn defnyddio'r gwerth hwn ar gyfer gweithrediadau chwilio oherwydd Defnyddir mynegeion ar gyfer chwilio. Er mwyn arbed lle, mae ES yn storio dogfen ffynhonnell gywasgedig. Os mai dim ond yr id sydd ei angen arnom, ac nid y ddogfen ffynhonnell gyfan, yna gallwn analluogi storio ffynhonnell.

Os nad oes angen gwybodaeth ychwanegol arnom, dim ond cynnwys _source y gallwn ei gael:

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

Gallwch hefyd ddewis rhai meysydd yn unig:

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

Gadewch i ni fynegeio ychydig mwy o bostiadau a rhedeg ymholiadau mwy cymhleth.

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

Trefnu

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

Dewison ni'r post olaf. size cyfyngu ar nifer y dogfennau i'w cyhoeddi. total yn dangos cyfanswm nifer y dogfennau sy'n cyfateb i'r cais. sort yn yr allbwn yn cynnwys amrywiaeth o gyfanrifau ar gyfer didoli yn cael ei berfformio. Y rhai. troswyd y dyddiad yn gyfanrif. Mae rhagor o wybodaeth am ddidoli ar gael yn dogfennaeth.

Hidlau ac ymholiadau

ES gan nad yw fersiwn 2 yn gwahaniaethu rhwng hidlwyr ac ymholiadau, yn lle hynny cyflwynir y cysyniad o gyd-destunau.
Mae cyd-destun ymholiad yn wahanol i gyd-destun hidlydd gan fod yr ymholiad yn cynhyrchu _score ac nid yw wedi'i storio. Byddaf yn dangos i chi beth yw _score yn ddiweddarach.

Hidlo yn ôl dyddiad

Rydym yn defnyddio'r cais ystod yng nghyd-destun hidlydd:

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

Hidlo yn ôl tagiau

Rydym yn defnyddio ymholiad tymor i chwilio am ddulliau adnabod dogfennau sy'n cynnwys gair penodol:

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

Chwiliad testun llawn

Mae tair o'n dogfennau yn cynnwys y canlynol yn y maes cynnwys:

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

Rydym yn defnyddio ymholiad cyfatebol i chwilio am ddulliau adnabod dogfennau sy'n cynnwys gair penodol:

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

Fodd bynnag, os chwiliwn am “straeon” yn y maes cynnwys, ni fyddwn yn dod o hyd i unrhyw beth, oherwydd Dim ond y geiriau gwreiddiol sydd yn y mynegai, nid eu coesynnau. Er mwyn gwneud chwiliad o ansawdd uchel, mae angen i chi ffurfweddu'r dadansoddwr.

Maes _score sioeau perthnasedd. Os gweithredir y cais mewn cyd-destun hidlydd, yna bydd y gwerth _score bob amser yn hafal i 1, sy'n golygu cyfatebiaeth gyflawn i'r hidlydd.

Dadansoddwyr

Dadansoddwyr sydd eu hangen i drosi'r testun ffynhonnell yn set o docynnau.
Mae dadansoddwyr yn cynnwys un Tocynydd a sawl dewisol TokenFilters. Gall Tokenizer gael ei ragflaenu gan sawl un Hidlyddion Char. Mae tocynwyr yn torri'r llinyn ffynhonnell yn docynnau, fel bylchau a nodau atalnodi. Gall TokenFilter newid tocynnau, dileu neu ychwanegu rhai newydd, er enghraifft, gadael coesyn y gair yn unig, tynnu arddodiaid, ychwanegu cyfystyron. CharFilter - yn newid y llinyn ffynhonnell gyfan, er enghraifft, yn torri allan tagiau html.

Mae gan ES sawl un dadansoddwyr safonol. Er enghraifft, dadansoddwr Rwsia.

Gadewch i ni gymryd mantais api a gadewch i ni weld sut mae'r dadansoddwyr safonol a Rwsiaidd yn trawsnewid y llinyn “Straeon doniol am gathod bach”:

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

Holltodd y dadansoddwr safonol y llinyn â bylchau a throsi popeth i lythrennau bach, tynnodd y dadansoddwr Rwsiaidd eiriau dibwys, ei drosi i briflythrennau a gadael coesyn y geiriau.

Gadewch i ni weld pa Tokenizer, TokenFilters, CharFilters y mae'r dadansoddwr Rwsia yn eu defnyddio:

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

Gadewch i ni ddisgrifio ein dadansoddwr yn seiliedig ar Rwsieg, a fydd yn torri allan tagiau html. Gadewch i ni ei alw'n ddiofyn, oherwydd bydd dadansoddwr gyda'r enw hwn yn cael ei ddefnyddio yn ddiofyn.

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

Yn gyntaf, bydd yr holl dagiau HTML yn cael eu tynnu o'r llinyn ffynhonnell, yna bydd y safon tokenizer yn ei rannu'n docynnau, bydd y tocynnau canlyniadol yn symud i lythrennau bach, bydd geiriau di-nod yn cael eu tynnu, a bydd y tocynnau sy'n weddill yn aros yn goesyn y gair.

Creu mynegai

Uchod fe wnaethom ddisgrifio'r dadansoddwr rhagosodedig. Bydd yn berthnasol i bob maes llinyn. Mae ein post yn cynnwys amrywiaeth o dagiau, felly bydd y tagiau hefyd yn cael eu prosesu gan y dadansoddwr. Achos Rydyn ni'n chwilio am bostiadau sy'n cyfateb yn union i dag, yna mae angen i ni analluogi dadansoddiad ar gyfer y maes tagiau.

Gadewch i ni greu blog mynegai2 gyda dadansoddwr a mapio, lle mae'r dadansoddiad o'r maes tagiau wedi'i analluogi:

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

Gadewch i ni ychwanegu'r un 3 neges i'r mynegai hwn (blog2). Byddaf yn hepgor y broses hon oherwydd... mae'n debyg i ychwanegu dogfennau at fynegai'r blogiau.

Chwiliad testun llawn gyda chefnogaeth mynegiant

Gadewch i ni edrych ar fath arall o gais:

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

Achos Rydym yn defnyddio dadansoddwr gyda choesyn Rwsieg, yna bydd y cais hwn yn dychwelyd yr holl ddogfennau, er eu bod yn cynnwys y gair 'hanes' yn unig.

Gall y cais gynnwys nodau arbennig, er enghraifft:

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

Cystrawen cais:

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

cyfeiriadau

PS

Os oes gennych ddiddordeb mewn erthyglau-gwersi tebyg, os oes gennych syniadau ar gyfer erthyglau newydd, neu os oes gennych gynigion ar gyfer cydweithredu, yna byddaf yn falch o dderbyn neges mewn neges bersonol neu drwy e-bost [e-bost wedi'i warchod].

Ffynhonnell: hab.com