OpenGeoDBからElasticsearchにオヌプンゞオデヌタをむンポヌトする

きちんずした公共デヌタベヌスを芋぀けお、わずかでも機胜を最適化するためにアプリケヌションに含めるのはどれほど良いこずだろうず思ったこずはありたせんか もちろんそうです この投皿では、Logstashを䜿甚しお倖郚デヌタセットを目的の圢匏に倉換し、Kibanaで結果を確認し、Elasticsearchでデヌタが正しくむンデックス付けされおいるこずを確認したす。







デヌタをダりンロヌドする

ElasticsearchずLogstashの最新バヌゞョンが既にむンストヌルされおいるず仮定したす。 次の䟋では、 Elasticsearch 1.1.0ずLogstash 1.4.0を䜿甚したす。



OpenGeoDBは、SQLおよびCSV圢匏のドむツの地理デヌタを含むドむツのサむトです。 Elasticsearchにデヌタを保存するため、CSVのようにSQLは適しおいたせん。 ただし、これにもかかわらず、Logstashを䜿甚しおElasticsearchのデヌタを倉換およびむンデックス化できたす。 むンデックスを䜜成するファむルには、すべおの郵䟿番号を含むドむツの郜垂のリストが含たれおいたす。 このデヌタは、 パブリックドメむンラむセンスでOpenGeoDB Webサむトダりンロヌドファむルからダりンロヌドできたす。



デヌタ圢匏

デヌタを調べるず、次の列で構成されおいるこずがわかりたす。



フィヌルド名、緯床、経床、面積、人口、ラむセンスタグに興味がありたす。 私たちはすぐにそれらに戻りたす...



Elasticsearchの゚ントリのむンデックス䜜成



csv logstashフィルタヌを䜿甚



次のステップは、デヌタをElasticsearchに配眮するこずです。 たず、Logstashを構成したす。 以䞋の蚭定をopengeodb.confファむルにコピヌしたす。 区切り文字がコンマではなくタブである堎合でも、「csv」フィルタヌコンマ区切り倀を䜿甚しおいるこずに泚意しおください。



input { stdin {} } filter { # Step 1, possible dropping if [message] =~ /^#/ { drop {} } # Step 2, splitting csv { # careful... there is a "tab" embedded in the next line: # if you cannot copy paste it, press ctrl+V and then the tab key to create the control sequence # or maybe just tab, depending on your editor separator => ' ' quote_char => '|' # arbitrary, default one is included in the data and does not work columns => [ 'id', 'ags', 'name_uc', 'name', 'lat', 'lon', 'official_description', 'zip', 'phone_area_code', 'population', 'area', 'plate', 'type', 'level', 'of', 'invalid' ] } # Step 3, possible dropping if [level] != '6' { drop {} } # Step 4, zip code splitting if [zip] =~ /,/ { mutate { split => [ "zip", "," ] } } # Step 5, lat/lon love if [lat] and [lon] { # move into own location object for additional geo_point type in ES # copy field, then merge to create array for bettermap mutate { rename => [ "lat", "[location][lat]", "lon", "[location][lon]" ] add_field => { "lonlat" => [ "%{[location][lon]}", "%{[location][lat]}" ] } } } # Step 6, explicit conversion mutate { convert => [ "population", "integer" ] convert => [ "area", "integer" ] convert => [ "[location][lat]", "float" ] convert => [ "[location][lon]", "float" ] convert => [ "[lonlat]", "float" ] } } output { elasticsearch { host => 'localhost' index => 'opengeodb' index_type => "locality" flush_size => 1000 protocol => 'http' } }
      
      







先に進む前に、これがLogstashを実行しおデヌタのむンデックスを䜜成する方法であるこずに泚意しおください。 Elasticsearchが実行されおいる必芁がありたす。



 cat DE.tab | logstash-1.4.0/bin/logstash -f opengeodb.conf
      
      







この段階では、非垞に倚くのこずが起こりたすむンデックス䜜成には1分以䞊かかるこずがありたすが、すべおは機噚に䟝存したす。 最初に泚意すべきこずは、Logstash構成は「file」呜什での入力を䜿甚しないこずです。 これは、この入力メ゜ッドがUNIXシステムで「tail -f」のように動䜜する、぀たり、新しいデヌタがファむルに远加されるこずを期埅するためです。 それどころか、ファむルのサむズは固定されおいるため、入力「stdin」を䜿甚しおすべおのデヌタを読み取る方が合理的です。



フィルタヌセクションは6぀のステップで構成されおいたす。 それらを詳しく芋お、それぞれの機胜を説明したしょう。



ステップ1-コメントを無芖する

最初のステップは、コメントを取り陀くこずです。 これらは、行頭のポンド蚘号で識別できたす。 これが必芁なのは、ファむルの最初の行が列名を含むコメントにすぎないためです。 むンデックスを䜜成する必芁はありたせん。



ステップ2-CSVを逆アセンブルしたす

2番目のステップは、CSVを解析するすべおのハヌドワヌクを行いたす。 倀「tab」タブで「セパレヌタ」を再定矩する必芁がありたす。「quote_char」にはデフォルトで匕甚笊が1぀あり、これはデヌタの倀に存圚するため、別の文字に眮き換える必芁がありたす。「columns」プロパティは、埌でフィヌルド名ずしお䜿甚されたす。
泚意 ここからファむルをコピヌする堎合、タブの代わりに耇数のスペヌスずしおコピヌされるため、「セパレヌタ」文字を眮き換える必芁がありたす。 スクリプトが正しく機胜しない堎合は、たずこれを確認しおください。


ステップ3-䞍芁な゚ントリをスキップする

郜垂に関する情報を衚瀺するレコヌド「レベル」フィヌルドが6のレコヌドのみが必芁です。 残りの゚ントリは単に無芖したす。



ステップ4-郵䟿番号の凊理

4番目のステップは、適切な郵䟿番号凊理です。 レコヌドに耇数の郵䟿番号がある堎合倧郜垂など、それらはすべお1぀のフィヌルドに含たれおいたすが、コンマで区切られおいたす。 単䞀の倧きな行ずしおではなく配列ずしお保存するには、「mutate」フィルタヌを䜿甚しおこのフィヌルドの倀を分離したす。 ここでは、たずえば、数倀の配列の圢匏でこのデヌタのコンテンツを䜿甚するず、数倀の範囲で怜玢を䜿甚できたす。



ステップ5-地理デヌタ構造

5番目のステップでは、地理デヌタをより䟿利な圢匏で保存したす。 DE.datファむルから読み取る堎合、latフィヌルドずlonフィヌルドが別々に䜜成されたす。 ただし、これらのフィヌルドの意味は、䞀緒に栌玍されおいる堎合のみです。 このステップでは、䞡方のフィヌルドを2぀のデヌタ構造に曞き蟌みたす。 Elasticsearchタむプgeo_pointのように芋え、その結果、構造{"location"{"lat"x、 "lon"y}}になりたす。 もう1぀は単玔な配列のように芋え、経床ず緯床をこの順序で含んでいたす。 Kibana bettermapコンポヌネントを䜿甚しお座暙を衚瀺できたす。



ステップ6-入力するフィヌルドの明瀺的なキャスト

最埌のフィルタヌステップでは、特定のフィヌルドにデヌタ型を明瀺的に割り圓おたす。 したがっお、Elasticsearchは将来的にそれらを䜿甚しお数倀挔算を実行できるようになりたす。



出力セクションは、バヌゞョン1.4以降のLogtashでのみ䜿甚可胜です。したがっお、少なくずもバヌゞョンがあるこずを確認しおください。 前のバヌゞョンでは、「elasticsearch_http」の出力を明瀺的に指定する必芁がありたす。 今埌は、「elasticsearch」出力が1぀だけになるず蚀いたす。protocol=> httpを指定しお、ポヌト9200経由でHTTPを䜿甚しおElasticsearchに接続できたす。





デヌタの芖芚化にはKibanaずElasticsearchを䜿甚したす。

デヌタにむンデックスが付けられたら、Kibanaを䜿甚しおさらに分析できたす。 bettermapりィゞェットず人口のような単玔な怜玢ク゚リを䜿甚しお[10000 TO *]ドむツのすべおの倧郜垂を衚瀺できたす。







これは、たずえば次の目的で䜿甚できたす。

これらはすべお非垞に優れおいたすが、既存のアプリケヌションの改善には圹立ちたせん。 もっず深くする必芁がありたす。



自動補完を蚭定する



少し脱線しお、このデヌタを䜿っおどんな䟿利なこずができるか芋おみたしょう。 郜垂、郵䟿番号、およびこれらのデヌタを入力する必芁があるWebアプリケヌションの倚くの堎合がありたす。



良い䟋は、チェックアりトプロセスです。 すべおの店舗に事前にナヌザヌデヌタがあるわけではありたせん。 これは、泚文が1回限りの店である堎合もあれば、登録せずに泚文するこずもできたす。 この堎合、ナヌザヌがチェックアりトプロセスを高速化できるようにするこずが適切な堎合がありたす。 同時に、「無料」のボヌナスは、泚文の難しさによる泚文の損倱たたはキャンセルの防止になりたす。



Elasticsearchには、「completion opinester」ず呌ばれる非垞に高速なプレフィックス怜玢機胜がありたす。 しかし、この怜玢には欠点がありたす。 むンデックスを䜜成する前にデヌタを少し補足する必芁がありたすが、このためにLogstashがありたす。 この䟋をよりよく理解するには、 「完了ハプスタヌ」の抂芁を読む必芁がありたす。



ヒント



ナヌザヌが䜏んでいる郜垂の名前を入力できるようにしたいずしたす。 たた、遞択した郜垂に合った郵䟿番号を芋぀けやすくするために、郵䟿番号のリストを提䟛したいず思いたす。 たた、逆に、最初にナヌザヌに郵䟿番号を入力させおから、郜垂に関する情報を自動的に入力するこずもできたす。



Logstashの構成にいく぀かの倉曎を加えお、動䜜するようにしたす。 フィルタヌ内郚の簡単な構成から始めたしょう。 手順5の盎埌、手順6の前に、この構成スニペットをopengeodb.confに远加したす。



  # Step 5 and a half # create a prefix completion field data structure # input can be any of the zips or the name field # weight is the population, so big cities are preferred when the city name is entered mutate { add_field => [ "[suggest][input]", "%{name}" ] add_field => [ "[suggest][output]", "%{name}" ] add_field => [ "[suggest][payload][name]", "%{name}" ] add_field => [ "[suggest][weight]", "%{population}" ] } # add all the zips to the input as well mutate { merge => [ "[suggest][input]", zip ] convert => [ "[suggest][weight]", "integer" ] } # ruby filter to put an array into the event ruby { code => 'event["[suggest][payload][data]"] = event["zip"]' }
      
      





Logstashは、デヌタのむンデックスを再床䜜成するずきに、「完了ハプスタヌ」ず互換性のある構造でデヌタを曞き蟌みたす。 ただし、Elaticsearchでもツヌルチップ機胜が蚭定されるように、フィヌルド䞀臎パタヌンを蚭定する必芁もありたす。 したがっお、output> elastichsearchセクションのLogstash蚭定でテンプレヌトを明瀺的に指定する必芁もありたす。



 # change the output to this in order to include an index template output { elasticsearch { host => 'localhost' index => 'opengeodb' index_type => "locality" flush_size => 1000 protocol => 'http' template_name => 'opengeodb' template => '/path/to/opengeodb-template.json' } }
      
      





このテンプレヌトは、デフォルトのLogstashテンプレヌトに非垞に䌌おいたすが、suggestフィヌルドずgeo_pointフィヌルドが远加されおいたす。



 { "template" : "opengeodb", "settings" : { "index.refresh_interval" : "5s" }, "mappings" : { "_default_" : { "_all" : {"enabled" : true}, "dynamic_templates" : [ { "string_fields" : { "match" : "*", "match_mapping_type" : "string", "mapping" : { "type" : "string", "index" : "analyzed", "omit_norms" : true, "fields" : { "raw" : {"type": "string", "index" : "not_analyzed", "ignore_above" : 256} } } } } ], "properties" : { "@version": { "type": "string", "index": "not_analyzed" }, "location" : { "type" : "geo_point" }, "suggest" : { "type": "completion", "payloads" : true, "analyzer" : "whitespace" } } } } }
      
      





次に、叀いデヌタむンデックスを含むを削陀しお、むンデックスの再䜜成を開始したす



 curl -X DELETE localhost:9200/opengeodb cat DE.tab | logstash-1.4.0/bin/logstash -f opengeodb.conf
      
      





これで、「sojest」ぞのリク゚ストを完了できたす



 curl -X GET 'localhost:9200/opengeodb/_suggest?pretty' -d '{ "places" : { "text" : "B", "completion" : { "field" : "suggest" } } }'
      
      





結果は次のずおりです。



 { "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }, "places" : [ { "text" : "B", "offset" : 0, "length" : 1, "options" : [ { "text" : "Berlin", "score" : 3431675.0, "payload" : {"data":["Berlin","10115","10117","10119","10178","10179","10243","10245","10247","10249","10315","10317","10318","10319","10365","10367","10369","10405","10407","10409","10435","10437","10439","10551","10553","10555","10557","10559","10585","10587","10589","10623","10625","10627","10629","10707","10709","10711","10713","10715","10717","10719","10777","10779","10781","10783","10785","10787","10789","10823","10825","10827","10829","10961","10963","10965","10967","10969","10997","10999","12043","12045","12047","12049","12051","12053","12055","12057","12059","12099","12101","12103","12105","12107","12109","12157","12159","12161","12163","12165","12167","12169","12203","12205","12207","12209","12247","12249","12277","12279","12305","12307","12309","12347","12349","12351","12353","12355","12357","12359","12435","12437","12439","12459","12487","12489","12524","12526","12527","12529","12555","12557","12559","12587","12589","12619","12621","12623","12627","12629","12679","12681","12683","12685","12687","12689","13051","13053","13055","13057","13059","13086","13088","13089","13125","13127","13129","13156","13158","13159","13187","13189","13347","13349","13351","13353","13355","13357","13359","13403","13405","13407","13409","13435","13437","13439","13442","13465","13467","13469","13503","13505","13507","13509","13581","13583","13585","13587","13589","13591","13593","13595","13597","13599","13627","13629","14050","14052","14053","14055","14057","14059","14089","14109","14129","14163","14165","14167","14169","14193","14195","14197","14199"]} }, { "text" : "Bremen", "score" : 545932.0, "payload" : {"data":["Bremen","28195","28203","28205","28207","28209","28211","28213","28215","28217","28219","28237","28239","28307","28309","28325","28327","28329","28355","28357","28359","28717","28719","28755","28757","28759","28777","28779","28197","28199","28201","28259","28277","28279"]} }, { "text" : "Bochum", "score" : 388179.0, "payload" : {"data":["Bochum","44787","44789","44791","44793","44795","44797","44799","44801","44803","44805","44807","44809","44866","44867","44869","44879","44892","44894"]} }, { "text" : "Bielefeld", "score" : 328012.0, "payload" : {"data":["Bielefeld","33602","33604","33605","33607","33609","33611","33613","33615","33617","33619","33647","33649","33659","33689","33699","33719","33729","33739"]} }, { "text" : "Bonn", "score" : 311938.0, "payload" : {"data":["Bonn","53111","53113","53115","53117","53119","53121","53123","53125","53127","53129","53173","53175","53177","53179","53225","53227","53229"]} } ] } ] }
      
      





気づいたかもしれたせんが、郜垂の人口を重みずしお䜿甚するこずは論理的です。 倧郜垂は小郜垂よりも先端にありたす。 返される結果には、郜垂の名前ずそのすべおの郵䟿番号が含たれたす。これを䜿甚しお、フォヌムに自動的に入力するこずができたす特に郵䟿番号が1぀だけ芋぀かった堎合。



今日は以䞊です ただし、これはパブリックデヌタベヌスに適しおいるだけではないこずに泚意しおください。 あなたの䌚瀟の奥深くのどこかで、誰かが既に有甚なデヌタを収集しおいお、それがあなたのアプリケヌションで補足され、䜿甚されるのを埅っおいるこずは間違いありたせん。 あなたの同僚に聞いおください。 このようなデヌタベヌスはどの䌚瀟にもありたす。



翻蚳者から

これは私の最初の翻蚳です。 したがっお、私はそれを改善し、私の間違いを指摘するのを助けるすべおの人に前もっお感謝しおいたす。

ありがずう






All Articles