ElasticSearch高速全文検索

画像

負荷の高いサイトまたは企業システムを開発する場合、高速で便利な検索エンジンの開発で問題がしばしば発生します。 私の意見では、このようなエンジンの要件は次のとおりです。





これらすべての要件を完全に満たす新しい検索エンジンElasticsearchについてお話したいと思います。 この記事には、簡単な説明、信頼できるプレゼンテーションへのリンク、およびインストールの説明とその作業が含まれます。



現在、このようなシステムにはさまざまな実装があり、それぞれに長所と短所があります。 私はこの分野の専門家ではないため、以下の情報はすべて私の主観的な意見としてのみ理解してください。



それで、最近、Andrei Zmievsky(Andrei Zmievski)のプレゼンテーションに出会い、そこで彼はelasticsearchの可能性を説明しました。 プレゼンテーションはここ (英語)で見ることができます。



プロジェクトのウェブサイトhttp://www.elasticsearch.org/



残念ながら、ロシア語で情報を見つけることができませんでした。



これは何?



実際、これは広く知られているLuceneインデックスの新しいフロントエンドです。 競合他社との主な違いは、柔軟性と使いやすさです。 インデックスへの情報の追加とインデックスによる検索は、単純なHTTPリクエストを使用して実行されます。



エンジンのインストールと使用例



私はこのトピックに興味があり、この奇跡エンジンを個人的にテストすることにしました。

それでは始めましょう



設置


	 1.アーカイブ(http://www.elasticsearch.org/download/)をダウンロードし、解凍します
	 2.サーバーを起動します 
		 Unix:bin / elasticsearch –f
		 Windows:bin / elasticsearch.bat
	 3.サーバーを確認します 
		 curl -X GET http:// localhost:9200 /
	すべてが機能する場合、サーバーはいくつかの情報を含むJSON配列を返します。


データの索引付け


例として、habrのユーザーインデックスを作成します



最初のユーザーに関するデータを追加します

 $ curl -XPUT 'http:// localhost:9200 / habrahabr / users / 1' -d '
 { 
  「名」:「Piotr」、
  「姓」:「ペトロフ」、
  「birthDate」:「1981-01-01」、
   「場所」:「モスクワ、ロシア連邦」、
  「スキル」:[「PHP」、「HTML」、「C ++」、「。NET」、「JavaScript」]
 } '


2番目のユーザーに関するデータを追加する

 $ curl -XPUT 'http:// localhost:9200 / habrahabr / users / 2' -d '
 { 
  「名」:「イヴァン」、
  「姓」:「シドロフ」、
  「birthDate」:「1978-12-13」、
   「場所」:「ロシア、ブライアンスク」、
  「スキル」:[「HTML」、「Ruby」、「Python」]
 } '


3番目のユーザーを追加する

 $ curl -XPUT 'http:// localhost:9200 / habrahabr / users / 3' -d '
 { 
  「名」:「ステパン」、
  「姓」:「Fomenko」、
  「birthDate」:「1985-06-01」、
   「場所」:「ウクライナ」、
  「スキル」:[「HTML」、「XML」、「Java」、「JavaScript」]
 } '


検索:ビジネスで試す


参考までに、簡単な検索例をいくつか紹介します。 実際、このエンジンは「エラスティック」という名前と完全に一致しており、さまざまなクエリを作成できます。 リクエストの詳細については、プロジェクトWebサイトwww.elasticsearch.org/guide/reference/apiをご覧ください。



パラメーターpretty = trueは、より読みやすい方法で回答を表示します



例1:Ivanという名前のすべてのユーザーを検索する

 $ curl -XGET 'http:// localhost:9200 / habrahabr / users / _search?q =名:Ivan&pretty = true'


例2:PHPの知識があるウクライナのすべてのユーザーを検索する

 $ curl -XGET 'http:// localhost:9200 / habrahabr / users / _search?pretty = true' -d '
 { 
     「クエリ」:{ 
         「term」:{「location」:「ウクライナ」、「skills」:「PHP」} 
     } 
 } '


例3:ロシアのユーザーを探す

 $ curl -XGET 'http:// localhost:9200 / habrauser / _search?q = location:Russian%20Federation&pretty = true'


例4:ロシアからのユーザー数を数える

 $ curl -XGET 'http:// localhost:9200 / habrauser / _count?q = location:Russian%20Federation&pretty = true'


PS UTF8は細かいサポート



高データテスト



残念ながら、他の検索エンジンでの作業経験はあまりないので、それらをelasticsearchと比較する方法はありません。 好奇心のために、5,000,000ユーザーのインデックスを作成することにしました。



インデックスを作成する簡単なスクリプト(データは生成されますが、情報は実際のものとほぼ同じです)



<?php ini_set('max_execution_time', 36000); class userGenerator { //       private $countries = array( 'Russian Federation', 'Ukraine', 'Germany', 'France', 'Lithuania', 'Latvia', 'Poland', 'Finland', 'Sweden' ); public function run($cnt) { for ($i = 0; $i < $cnt; $i++) { $query = $this->generateQuery($i); echo "generating user " . $i . " ... "; exec($query); echo "done" . PHP_EOL; } } private function generateQuery($id) { //       1960-  $date = new DateTime('1960-01-01'); return 'curl -XPUT \'http://localhost:9200/habrahabr/users/' . $id . '\' -d \' { "id" : "' . $id . '", "firstname" : "' . ucfirst($this->generateWord(10)) . '", "surname" : "' . ucfirst($this->generateWord(10)) . '", "birthDate" : "' . $date->modify('+' . rand(0, 14600) . ' days')->format('Ym-d') . '", "location" : "' . $this->generateWord(10) . ', ' . $this->countries[array_rand($this->countries)] . '", "skills" : ["' . strtoupper($this->generateWord(3)) . '", "' . strtoupper($this->generateWord(4)) . '", "' . strtoupper($this->generateWord(3)) . '"] }\' '; } private function generateWord($length) { $letters = array( "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"); $word = ''; for ($i = 0; $i < $length; $i++) { $word .= $letters[rand(0, 25)]; } return $word; } } $generator = new userGenerator(); $generator->run(5000000); echo "complete"; ?>
      
      







自宅(非常に強力ではない)のPCでインデックスを作成するのに約5時間かかりました。 何も設定も最適化もしなかったという事実を考えると、結果はかなり良いと思います。 さらに、インデックスの生成時間は私にとって特に重要ではありません。 設定を詳しく調べて、単一ではなくグループリクエスト(詳細はこちら )を送信するようにスクリプトを最適化すれば、時間が数倍短縮されると思います。 さて、このプロセスも並列化すると、時間を1時間に短縮できます。



インデックスのエントリ数を確認してください

  curl -XGET 'http:// localhost:9200 / habrahabr / users / _count?q = *&pretty'
 {
   「カウント」:5128888、
   「_shards」:{
     「合計」:5
     「成功」:5
     「失敗」:0
   }




新しいレコードを追加する速度を確認してください

 時間カール-XPUT 'http:// localhost:9200 / habrahabr / users / 5128889' -d '
 { 
  「名」:「バジル」、
  「姓」:「フェドロフ」、
  「birthDate」:「1975-07-11」、
   「場所」:「リガ、ラトビア」、
  「スキル」:[「PERL」、「PYTHON」、「ActionScript」]
 } '
 {"ok":true、 "_ index": "habrahabr"、 "_ type": "users"、 "_ id": "5128891"、 "_ version":2}

実際の0m0.007s
ユーザー0m0.004s
 sys 0m0.000s




情報検索の速度を確認する

 time curl -XGET 'http:// localhost:9200 / habrahabr / users / _search?q =場所:Riga&pretty'
 {
   「取った」:5
   「timed_out」:false、
   「_shards」:{
     「合計」:5
     「成功」:5
     「失敗」:0
   }、
   「ヒット」:{
     「合計」:1、
     「max_score」:8.854725、
     「ヒット」:[{
       「_index」:「habrahabr」、
       「_type」:「users」、
       「_id」:「5128891」、
       「_score」:8.854725、「_ source」: 
 { 
  「名」:「バジル」、
  「姓」:「フェドロフ」、
  「birthDate」:「1975-07-11」、
   「場所」:「リガ、ラトビア」、
  「スキル」:[「PERL」、「PYTHON」、「ActionScript」]
 }
     }]
   }
 }
実数0m0.011s
ユーザー0m0.004s
 sys 0m0.000s




 $ time curl -XGET 'http:// localhost:9200 / habrahabr / users / _count?q =場所:Germany&pretty'
 {
   「カウント」:570295、
   「_shards」:{
     「合計」:5
     「成功」:5
     「失敗」:0
   }
 }
実数0m0.079s
ユーザー0m0.004s
 sys 0m0.000s




結論


私の意見では、エンジンは高速で高品質で使いやすいです。 同じZend_Search_Luceneよりもずっと高速です。



この記事では、その機能のごく一部、つまり最も単純で最も原始的な機能のみを説明しました。 この記事以外では、トランザクション、レプリケーション、フィルター、およびその他の多くの便利な機能が残っています。 また、このエンジン用のライブラリはすでにJavaおよびPHP(他の言語で作成されている可能性があります)で記述されていることにも言及する価値があります。



追伸 私はテキストと用語のいくつかの行き詰まりをおizeびします。



All Articles