이 기사에는 Elasticsearch의 특정 원칙이 포함되어 있지 않지만 전체 텍스트 검색을 위해 MySQL에서 데이터를 빠르게 가져 오는 방법 만 기록합니다.
직장에서 검색 기능을 구현하고 기존 데이터베이스 데이터를 가져와야합니다. 팀장은 ElasticSearch를 사용하여 구현할 것을 권장합니다. 비교적 오래된 기사 인 온라인 튜토리얼을 통해 검색 할 수 있습니다. 나는 그것을 스스로 탐구하는 것 외에는 선택의 여지가 없습니다. ES 문서를 참조하고 마지막으로 서비스를 구축하십시오. 나는 그것을 기록 할 것이다. 동일한 요구를 가진 친구들이 우회를 피하고이 튜토리얼에 따라 사용 가능한 Elasticsearch 서비스를 신속하게 구축 할 수 있기를 바랍니다.
ES 건설
ES 빌드는 Zip 파일과 Docker 컨테이너를 직접 다운로드 할 수 있습니다. 비교적 말하면 Docker는 ES 서비스를 운영하는 데 더 적합합니다. 클러스터를 쉽게 구축하거나 테스트 환경을 만들 수 있습니다. 컨테이너 방법도 여기에 사용됩니다. 먼저, 우리는 dockerfile이 필요합니다.
docker.elastic.co/elasticsearch/elasticsearch-oss 에서:6.0.0# 구성 제출 구성 제출 새로운 elasticsearch.yml 및 keystore.jks 파일을 포함하여 -chown = elasticsearch : elasticsearch conf//usr/share/config/# ikrun 설치 ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysy-ik/releases/download/v6.0.0/elasticsearch-analysis-ik-6.0.0.zip# readonlyrestrun 설치 ./bin/elasticsearch-plugin 설치 https://github.com/hyy-yu/beziercurvedemo/raw/mas
위의 작업에 대한 설명은 다음과 같습니다.
elictic configuration elasticsearch.yml
Cluster.Name : "Docker-Cluster"Network.host : 0.0.0.0# minimum_mas bootstrap.memory_lock : true http.type : ssl_netty4readonlyrest : enable : true ssl : enable : true keystore_file : "server.jks"keystore_pass : 서버 key_pass : - 이름 : "block 1 -root" - [aniver " - [user": "" "" "" "" "" "" "" " 지수 : [ "종이*"] 조치 : [ "인덱스 : 데이터/읽기/*"] 사용자 : - 사용자 이름 : root auth_key_sha256 : CB7C9BAE153065DB931980A13BD45E3A77CB8F27A7DFEE68686377ACC333F1 그룹 : Auth_key : Xiaoming : Xiaoming Groups : [ "사용자"]
여기 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", "버전": { "숫자": "6.0.0", "build_hash": "8f0685b", "build_date": "2017-11-10T18 : 41 : 22.859z", "build_snapshot": false, "lucene_version": "7.0.1", "minimum_wire_compatibility_version": "5.6.0", "minimum_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 | 베이징 1 번 초등학교 시뮬레이션 |
| 2 | Jiangxi 베이징 일반 대학 입학 시험 질문 |
지방 테이블
| ID | 이름 |
|---|---|
| 1 | 베이징 |
| 2 | Jiangxi |
paper_province 테이블
| paper_id | Province_id |
|---|---|
| 1 | 1 |
| 2 | 1 |
| 2 | 2 |
위에서 언급했듯이 종이와 지방은 다수의 관계입니다. 이제 종이 데이터가 ES로 입력되었으므로 종이 이름으로 모호하게 검색하거나 지방을 통해 필터링 할 수 있습니다. JSON 데이터 형식은 다음과 같습니다.
{ "id": 1, "이름": "베이징 No. 1 초등학교 시뮬레이션 볼륨", "지방": [{ "id": 1, "name": "Beijing"}]} 먼저 Mapping.json 파일을 준비합니다.이 파일은 ES의 데이터의 스토리지 구조 정의입니다.
{ "매핑": { "docs": { "includ_in_all": false, "properties": { "id": { "type": "long"}, "name": { "type": "text", "analyzer": "Ik_max_word"// "가장 큰 단어 구문 분석기": { "type": "" "" "" "" "id": { "type": "integer"}, "name": { "type": "text", "index": "false"// 색인 "}}}}}}}}}}}},"settings ": {"number_of_shards ": 1,"number_of_replicas ": 0}}_all 필드가 취소되었습니다. 이 기본값 _all은 무조건 제한 검색을 달성하기 위해 모든 스토리지 필드를 수집합니다. 단점은 공간이 많이 점유된다는 것입니다.
샤드 번호를 1로 설정했으며 복제본이 설정되지 않았습니다. 결국, 이것은 클러스터가 아니며 처리 된 데이터는 그다지 많지 않습니다. 처리 해야하는 많은 양의 데이터가 있으면 샤드와 복제본 수를 직접 설정할 수 있습니다.
먼저, ES와의 연결을 확립합니다. ca.crt는 JKS 자체 서명과 관련이 있습니다. 물론 여기에서는 인증서 파일의 확인을 무시하기 위해 불안정 검사를 사용하고 있습니다.
funcc initelasticsearch () {pool : = x509.newcertpool () crt, err0 : = ioutil.readfile ( "conf/ca.crt") if err0! = nil {err0, "읽기 crt 파일 err") return} pool.appendcertsfremm (crt) tr : = & http.transport {tlsclientsport} & tls.config {rootcas : pool, insecureskipverify : true},} httpclient : = & http.client {transport : tr} // 배경 구조 Elasticclient var err err elasticclient, err = elastic.newclient (elastic.seturl (myconfig.elasticurl), elastic.seterlog (getlogger) elastic.setgzip (true), elastic.sethttpclient (httpclient), elastic.setsniff (false), // 클러스터 스니프, 단일 노드를 닫아야합니다. "search_client_error") return} // elasticclient construction이 완료되었습니다. // 종이 인덱스가 있는지 여부 : err : = elasticclient.indexexists (myconfig.elasticindexname) .do (context.background ()) err! = nil {canceopenes (eRce_paper _check ") // indextity retist and the index and the exists and the index in the index 님. indistion {if! isindexintegrity (elasticclient)) {// 현재 색인을 삭제하고 deleterPonse를 재 구축 할 준비를하고 err : = elasticclient.deleteindex (myconfig.elasticindexName) .do (context.background ()) if err! = nil || ! deleterPonse.ackNowledged {caleopenes (err, "delete_index_error") return}} else {return}} // 배경 쿼리 데이터베이스 및 Elasticsearch Go FetchDBgetAllPaperandSendToes ()}에 데이터를 보냅니다. 유형의 paperSearch struct {PaperId int64` Gorm : "Primary_key; 컬럼 : f_paper_id; 유형 : bigint (20)"json : "id"`name string`gorm : "column : f_name; size : 80"json : "provinces [] province`province :"many2many : t_papov _prov; " JSON : "주"``// 테스트 논문이 적용 가능한 주정부} funccdbgetAllpaperandsendtoes () {// fetch paper var var allpaper [] papersearch getdb (). 표 ( "t_papers"). find (& allpaper) // province {var allpro [] getdb (). 테이블 ( "t_provinces"). 조인 allpaper [i] .paperid) .find (& allpro) allpaper [i] .provinces = allpro} if len (allpop)> 0 {// es -es -es -es -index createService : = getElasticsearch (). createIndex (myConfig.elasticIndexName) // 여기에있는 컨텐츠의 내용입니다. createService.body (index_default_setting) createresult, err : = createService.do (context.background ()) if err! = nil {nil {nil {create_paper_index "return} if! createresult.ackNowledged || createResult.sapeAlged vected. - 모든 종이 BulkRequest를 보내십시오 : = getElasticsearch (). bulk ()는 i : = range allpaper {indexreq : = elastic.newbulkindexrequest ( "create"). index (myconfig.elasticindexName). Doc (allpaper [i]) bulkrequest.add (indexreq)} // err! = nil {nil {insert_docs_error "return} // bulk 요청이 명확 해짐에 따라 (insert_docs_error") If Err! ! = LEN (AllPaper) {CALEOPENES (err, "insert_docs_nums_error") return} // send}}} 위의 코드를 실행 한 후 {{url}}/_ cat/indices? v를 사용하여 새로 생성 된 색인이 ES에 나타나는지 확인하고 {{url}}/papers/_search를 사용하여 얼마나 많은 문서를 쳤는지 확인하십시오. 문서 수가 과거에 보낸 데이터 양과 같으면 검색 서비스가 실행되는 것으로 간주됩니다.
찾다
이제 Provinceid와 Q에서 테스트지를 검색 할 수 있으며 기본값은 관련성 점수로 정렬됩니다.
// Q 검색 문자열 제한된 지방 ID 제한 페이지 페이지 페이지 매개 변수 (Q 문자열, 지방 UINT, 제한 int, Page int) (List [] PaperSearch, TotalPage int, CurrentPage int, PageIsend int, returnERR Error) {// 조건이 충족되지 않으면 검색을 위해 데이터베이스를 사용하여 RETURNESTICAL (canuseELastical)을 사용하여 데이터베이스를 사용합니다. Course, gradeid, provinceid, pacttypeid, limit, page)} list = make ([] papersimple, 0) totalpage = 0 currentpage = 0 pageisend = 0 returnerr = nil client : = getelasticsearch () 클라이언트 == nil {return searchpaperlocal (Q, courseid, grade, pactionpeorid, page, page, wat it and wat at at at at at at at retocticearn = 0 returnerr = nil client : = getelasticsearch (). 데이터베이스를 검색하는 데이터베이스! isindexintegrity (client) {return searchPappeplocal (q, courseId, gradeId, pactinceid, limit, page)} if! client.isRunning () {client.start ()} defer client.stop () q = html.escapestring (q) boolquery .newboolquery () newboolquery (). : = elastic.newmatchQuery ( "name", q) // province if provinceid> 0 && provinceid! = default_province_all {probool : = elastic.newboolquery () tpro : = elastic.newtermquery ( "provinces.id", provinceid) 우명 (elastic.newnestedquery). probool.must (tpro)) boolquery.must (pronest)} boolquery.must (matchQuery) _, e : = range termquerys {boolquery.must (e)} 하이라이트 : = elastic.newhighlight (elastic_search_search_name) 하이라이트 .pretags (elastic_search_search_field_tag_start) 하이라이트. 하이라이트 (Highligt). 쿼리 (boolquery). ((페이지 -1) * 한계). 크기 (한계). do (context.background ()) if err2! = nil {// 오류 getLogger (). logerr ( "+err2.error (),"search_error ") // hands error returnerr = orrors.new ("검색 중에 오류가 발생했습니다 ")를 검색하는 동안 오류가 발생했습니다. {if searchresult.hits.totalhits> 0 reestent for reestment for e. searchResult.hits.hits {var p papersearch err : = json.unmarshal (*hit.source, & p) err! = nil {// deserialization 실패 getLogger (). logerr ( "+err.error (),"search_deserialization_error ") returor = returors.new") LEN (HIT.HIGHLIGHT [ELASTIC_SEARCH_SEARCH_FIELD_NAME])> 0 {P.NAME = HIT.HIGHLIGHT [ELASTIC_SEARCH_SEARCH_SIRCH_NAME] [0]} LIST = LIST = APTEND (LIST, P)} COUNT : = SearchResult.Totalhits () currentPage = Page If Count> 0 {Count (Count) / Count (Count) / float64 (limit))} currentPage> = TotalPage {pageisend = 1}} else {// hits}} return}위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.