この記事には、ElasticSearchの特定の原則は含まれませんが、フルテキスト検索のためにMySQLにデータをすばやくインポートする方法のみを記録します。
職場では、検索機能を実装し、既存のデータベースデータをインポートする必要があります。チームリーダーは、ElasticSearchを使用して実装することをお勧めします。オンラインでチュートリアルを検索できます。これは比較的古い記事です。自分で探索するしかありません。 ESドキュメントを参照し、最終的にサービスを構築します。録音します。同じニーズを持つ友人が迂回を避け、このチュートリアルに従って利用可能なElasticsearchサービスをすばやく構築できることを願っています。
ES構造
ESビルドは、ZIPファイルとDockerコンテナを直接ダウンロードできます。比較的言えば、DockerはESサービスを実行するのに適しています。クラスターを簡単に構築したり、テスト環境を作成したりすることができます。コンテナ法もここで使用されます。まず、dockerfileが必要です。
docker.elastic.co/elasticsearch/elasticsearch-oss:6.0.0# From from new elasticsearch.yml and keystore.jksファイルを含む構成を送信コピー - chown = elasticsearch:elasticsearch conf//usr/share/elasticsearch/config/config/nistal https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.0.0/elasticsearch-analysis-ik-6.0.0.zip# Install readonlyRestrun ./bin/ElasticSearch-Pluginインストールhttps://github.com/hyy-yu/beziercurvedemo/raw/master/readonlyrest-1.16.14_es6.0.zipuser elasticsearchcmd ./bin/elasticsearch
上記の操作の説明は次のとおりです。
Elictic Configuration Elasticsearch.yml
cluster.name: "docker-cluster" network.host:0.0.0.0#miniminal_master_nodesは、パブリックIPにバインドされている場合に明示的に設定する必要があります#単一ノードクラスターを設定して1に設定して、https://github.com/Elastic/Elasticsearch/pull/17288Discovery.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen.zen. on ES bootstrap.memory_lock: true http.type: ssl_netty4readonlyrest: enable: true ssl: enable: true keystore_file: "server.jks" keystore_pass: server key_pass: server access_control_rules: - name: "Block 1 - ROOT" type: allow groups: ["admin"] - name: "User read only - paper" groups: ["user"] indices:["paper*"] action:["indices:data/read/*"] users:-username:root auth_key_sha256:cb7c98bae153065db931980a13bd45ee3a77cb8f27a7a7dfeee68f68f688888883777ac33f1 Xiaoming auth_key:xiaoming:xiaomingグループ:["user"]
ここで、bootstrap.memory_lock:trueはピットであり、メモリの交換を禁止しています。ドキュメントは、一部のOSがランタイム中に一時的に未使用のメモリをハードディスクの領域に交換することをすでに説明しています。ただし、この動作により、ESのリソース利用率が高まり、システムが応答できなくなります。
構成ファイルでは、ルートユーザーが管理グループに属し、管理者がすべての権限を持っていることはすでに明らかです。 Xiaomingはユーザーグループにあるため、彼は紙インデックスのみにアクセスすることができ、読み取ることができますが、動作することはできません。より詳細な構成については、readonlyrestドキュメントを参照してください
この時点で、ESの準備が完了しました。 docker build -t esimage:タグ。 docker run -p 9200:9200 esimage:タグ実行。
https://127.0.0.1:9200/返品の場合
{"name": "vakwrir"、 "cluster_name": "docker-cluster"、 "cluster_uuid": "ysydowkvrh2swz907s2m_w"、 "バージョン":{"number": "6.0.0"、 "build_hash": "8f0685b"、 "build_date": "8f0685b": " 「2017-11-10T18:41:22.859Z "、" build_snapshot ":false、" lucene_version ":" 7.0.1 "、" 5.6.0 "、" 5.6.0 "、" minimol_index_compatibility_version ":" 5.0.0私たちのチュートリアルの主人公が登場しました。一般的に使用されるいくつかのAPIを共有してESをからかい、デバッグします。
{{url}}は、ローカルESアドレスに置き換えられます。
MySQLデータをインポートします
ここではMySQLデータを使用していますが、実際、他のデータベースは同じです。重要なのは、インポートする方法です。オンラインチュートリアルでは、Logstash、Beat、およびES用のMySQLプラグインをインポート用に推奨します。私も試しました。構成は面倒で、ドキュメントはまばらです。データベース構造が少し複雑な場合、インポートは面倒な作業であるため、推奨されません。実際、ESは各言語に対応するAPIライブラリを持っています。言語レベルでデータをJSONに組み立てて、APIライブラリを介してESに送信できます。プロセスはほぼ次のとおりです。
GolangのESライブラリエラスティックを使用しています。 Githubで他の言語を検索でき、操作方法は同じです。
次に、簡単なデータベースを使用して紹介します。
紙のテーブル
| id | 名前 |
|---|---|
| 1 | 北京No. 1小学校のシミュレーション |
| 2 | Jiangxi General Collegeの入学試験の質問 |
州のテーブル
| id | 名前 |
|---|---|
| 1 | 北京 |
| 2 | jiangxi |
Paper_Provinceテーブル
| Paper_id | province_id |
|---|---|
| 1 | 1 |
| 2 | 1 |
| 2 | 2 |
上記のように、紙と州は多くの関係です。紙のデータがESに入力されたので、紙の名前でファジーに検索したり、州を介してフィルターをかけたりすることができます。 JSONデータ形式は次のとおりです。
{"id":1、 "name": "Beijing No. 1 Primary School Simulation Volume"、 "Provinces":[{"id":1、 "name": "Beijing"}]}最初に、ESのデータのストレージ構造定義であるMapping.jsonファイルを準備します。
{"mappings":{"docs":{"include_in_all":false、 "properties":{"id":{"type": "long"}、 "" type ":" text "、" aNalyzer ":" IK_MAX_WORD "// "id":{"type": "integer"}、 "name":{"type": "text"、 "index": "false" // not indexed}}}}}}}}}}}}}}_allフィールドがキャンセルされていることに注意する必要があります。このデフォルト_Allは、すべてのストレージフィールドを収集して、無条件の制限検索を実現します。欠点は、スペースが多くを占有していることです。
シャード番号を1に設定すると、レプリカが設定されていません。結局のところ、これはクラスターではなく、処理されたデータはそれほど多くありません。処理する必要があるデータが大量にある場合は、自分で破片とレプリカの数を設定できます。
まず、ESとのつながりを確立する、Ca.crtはJKSの自己署名に関連しています。もちろん、ここでは、証明書ファイルの検証を無視するためにInsecureSkipverifyを使用しています。
func initeLasticsearch(){pool:= x509.newcertpool()crt、err0:= ioutil.readfile( "conf/ca.crt")if err0!= nil {can can can can can cantabene( "read" read ")return} pool.appendcertsFrompem( &tls.config {rootcas:pool、insecureskipverify:true}、} httpclient:=&http.client {transport:tr} // elasticclient var err erry erlasticclient、err = elastic.newclient(elastic.seturl(myconfig.elasturl)、elastirlog()、elasty.setirlog()、elasty.seturrog()、elasty.seturrog() Elastic.setGzip(True)、Elastic.sethttpclient(httpclient)、Elastic.setsniff(false)、//クラスタースニッフ、elastic.setscheme( "https")、Elastic.setbasicauth(myconfig.elasticursername、myconfig.Elastig.Elastig.Elastic) Cantable(err、 "search_client_error")return} //弾性クライアントの構築が完了します整合性チェック、存在する場合、データは送信されません{if!isindexIntegrity(ElasticClient){//現在のインデックスを削除し、leteresponseを再構築する準備をします。 !deleteresponse.acknowledged {cantabin(err、 "delete_index_error")return}} ells {return}} //背景クエリデータベースとelasticsearch go fetchdbgetallpaperandsendtoes()}}にデータを送信Type PaperSearch struct {Paperid int64 `gorm:" primary_key; column:f_paper_id; type:bigint(20) "json:" id "` name string `gorm:" column:f_name; size:80 "json:" name "" comvinces [] cuntions `gorm:" many2many:t_papervince; " JSON:「州」 `//テストペーパーが該当する州の州} func fetchdbgetallpaperandsendtoes(){// fetch paper var allpaper [] papersearch getdb()。テーブル(" t_papers ")。 getdb()。table( "t_provinces")。 allpaper [i] .paperid).find(&allpro)allpaper [i] .provinces = allpro} if len(allpaper)> 0 {// esに送信 - index createSearch()。createindex(myconfig.elassindexname) createService.body(index_default_setting)createresult、err:= createService.do(context.background())if err!= nil {err、 "create_paper_index")return} - すべてのペーパーBulkRequest:= getElasticsearch()。 doc(allpaper [i])bulkrequest.add(indexreq)} // do do do do do do do do do do do do do do do do do do do do do do do do do do do elasticsearch bulkresponse、err:= bulkrequest.do(context.background())if err! != len(allpaper){cantabin(err、 "insert_docs_nums_error")return} //成功を送信}}}上記のコードを実行した後、{{url}}/_ cat/indices?vを使用して、新しく作成されたインデックスがESに表示されるかどうかを確認し、{{url}}/papers/_searchを使用して、ヒットするドキュメントの数を確認します。ドキュメントの数が過去に送信したデータの量に等しい場合、検索サービスは実行中と見なされます。
検索
これで、ProvenceIDとQによるテストペーパーを検索できるようになり、デフォルトは関連スコアでソートされます。
//q Search string provinceID Limited province id limit page pagination parameters func SearchPaper(q string, provinceId uint, limit int, page int) (list []PaperSearch, totalPage int, currentPage int, pageIsEnd int, returnErr error) { //If the conditions are not met, use the database to search if !CanUseElasticSearch && !MyConfig.UseElasticSearch { return SearchPaperLocal(q, COURSEID、GRADEID、PROVENCEID、PAPERTYPEID、LIMIT、PAGE)} list = make([] PaperSimple、0)TotalPage = 0 CurrentPage = Page PageIsend = 0 returnerr = nil client:= getElasticsearch()client == nil {return searchpaperlocal(q、courseid、gradeid、pagerid、paperid、paperid、paperid、paperid、umpedead、emced、eal IFを検索するデータベース!isIndexIntegrity(client){return searchpaperLocal(q、coursed、gradeid、provinceid、papertypeid、lime、page)} if!client.isrunning(){client.start()} defer client.stop()q = html.escapestring(q)boolqueer.newbqueery() := Elastic.newmatchquery( "name"、q)// provenceid> 0 && upentid!= default_province_all {robool:= lerastic.newboolquery()tpro:= leasty.newtermquery( "provinces.id"、argenceid:= Elastic.Newnestedquery( " probool.must(tpro))boolquery.must(pronest)} boolquery.must(matchquery)for _、e:= range termquerys {boolquery.must(e)} highlightt:= elastic.newhighlight.()highlight.field(elastic_search_search_name_name) highlight.pretags(Elastic_search_search_field_tag_start)highlight.posttags(Elastic_search_search_field_tag_end)searchResult、err2:= client.search(myconfig.ElastIndExname)。ハイライト(highligt)。クエリ(boolquery)。 ((ページ-1) *制限)から。サイズ(制限)。 do(context.background())err2!= nil {//エラーgetlogger()。 searchResult.hits.hits {var p papersearch err:= json.unmarshal(*hit.source、&p)err!= nil {// deserialization failed getlogger()。logerr( "search"+err.error()、 "search_deserialization_error")returner = error.new( "error( len(hit.highlight [Elastic_search_search_field_name])> 0 {p.name = hit.highlight [Elastic_search_search_field_name] [0]} list = append(list、p)} count:= searchResult.Totalhits()currentPage = page if count> 0 {totalpage = int(count(foot(floaat) / flot(fluaat) / count(curnt) float64(lime)))} if currentPage> = totalPage {pageisend = 1}} else {// no hits}} return}上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。