Elasticsearch اساسات

Elasticsearch د json rest api سره د لټون انجن دی، د Lucene په کارولو سره او په جاوا کې لیکل شوی. د دې انجن د ټولو ګټو توضیحات په کې شتون لري رسمي ویب پاڼه. په لاندې څه کې به موږ د ES په توګه Elasticsearch ته مراجعه وکړو.

ورته انجنونه د اسنادو په ډیټابیس کې د پیچلو لټونونو لپاره کارول کیږي. د مثال په توګه، د ژبې مورفولوژي په پام کې نیولو سره لټون یا د جیو همغږي په واسطه لټون.

پدې مقاله کې به زه د ES اساساتو په اړه وغږیږم د بلاګ پوسټونو شاخص کولو مثال په کارولو سره. زه به تاسو ته وښیم چې څنګه د اسنادو فلټر، ترتیب او لټون کول.

د دې لپاره چې په عملیاتي سیسټم پورې اړه ونلري، زه به د CURL په کارولو سره ES ته ټولې غوښتنې وکړم. د ګوګل کروم په نوم یو پلگ ان هم شتون لري احساس.

متن د اسنادو او نورو سرچینو لینکونه لري. په پای کې اسنادو ته د چټک لاسرسي لپاره لینکونه شتون لري. د ناپیژندل شوي اصطلاحاتو تعریفونه په کې موندل کیدی شي لغتونه.

د ES نصب کول

د دې کولو لپاره، موږ لومړی جاوا ته اړتیا لرو. پرمخ وړونکي سپارښتنه د جاوا 8 تازه 20 یا جاوا 7 تازه 55 څخه نوي جاوا نسخې نصب کړئ.

د 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 د یو واحد ارزښت او د ارزښتونو لړۍ ترمنځ توپیر نه کوي. د مثال په توګه، د سرلیک ساحه په ساده ډول یو سرلیک لري، او د ټاګ ساحه د تارونو لړۍ لري، که څه هم دوی په نقشه کولو کې په ورته ډول ښودل شوي.
موږ به وروسته د نقشې جوړولو په اړه نور خبرې وکړو.

غوښتنې

د خپل 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 رامینځته کوي او زیرمه شوي ندي. زه به تاسو ته وښیم چې وروسته _score څه دی.

د نیټې له مخې فلټر کړئ

موږ غوښتنه کاروو لړ د فلټر په شرایطو کې:

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

د ټاګونو لخوا فلټر کړئ

مونږ تری ګټه پورته کوو اصطلاح پوښتنه د اسنادو ids لټولو لپاره چې یو ورکړل شوی کلمه لري:

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

مونږ تری ګټه پورته کوو د میچ پوښتنه د اسنادو ids لټولو لپاره چې یو ورکړل شوی کلمه لري:

# 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 ښيي تړاو. که غوښتنه د فلټر په شرایطو کې اجرا شي، نو د _score ارزښت به تل د 1 سره مساوي وي، پدې معنی چې فلټر ته بشپړ میچ دی.

شنونکي

شنونکي د سرچینې متن د ټکنونو سیټ ته د بدلولو لپاره اړین دي.
شنونکي له یو څخه جوړ دي ټوکنسر او څو اختیاري TokenFilters. Tokenizer ممکن د څو لخوا مخکې وي چارفلټرونه. Tokenizers د سرچینې تار په ټوکنونو کې ماتوي، لکه ځایونه او د ټکي نښه حروف. TokenFilter کولی شي ټوکنونه بدل کړي، نوي حذف یا اضافه کړي، د بیلګې په توګه، یوازې د کلمې ډډ پریږدئ، وړاندیزونه لرې کړئ، مترادفات اضافه کړئ. چارفیلټر - د ټولې سرچینې تار بدلوي، د بیلګې په توګه، د html ټګونه پرې کوي.

ES ډیری لري معیاري تحلیل کونکي. د مثال په توګه، یو شنونکی روسي.

راځئ چې ګټه ترې واخلو API او راځئ وګورو چې معیاري او روسی تحلیل کونکي څنګه د "د پیشوګانو په اړه مسخره کیسې" تار بدلوي:

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

راځئ چې په دې شاخص کې ورته 3 پوسټونه اضافه کړو (blog2). زه به دا پروسه پریږدم ځکه چې ... دا د بلاګ شاخص ته د اسنادو اضافه کولو سره ورته دی.

د بیان ملاتړ سره د بشپړ متن لټون

راځئ چې یو بل ډول غوښتنه وګورو:

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

مرجع

PS

که تاسو د ورته مقالو - درسونو سره علاقه لرئ ، د نوي مقالو لپاره نظرونه لرئ ، یا د همکارۍ وړاندیز لرئ ، نو زه به خوښ شم چې په شخصي پیغام یا بریښنالیک کې پیغام ترلاسه کړم. [ایمیل خوندي شوی].

سرچینه: www.habr.com