머리말
이전 기사에서 SpringBoot, Mybatis, Druid 및 PageHelper가 통합되었으며 여러 데이터 소스의 작동이 구현되었습니다. 이 기사는 주로 가장 인기있는 검색 엔진 인 Elastisearch를 소개하고 사용하며 SpringBoot와 함께 사용합니다.
Elasticsearch 소개
Elasticsearch는 Lucene을 기반으로하는 검색 서버입니다. 실제로 루센을 캡슐화하고 REST API의 작동 인터페이스를 제공합니다. Elasticsearch는 빅 데이터를 신속하게 저장, 검색 및 분석하는 데 사용할 수있는 고도로 확장 가능한 오픈 소스 전체 텍스트 검색 및 분석 엔진입니다.
Elasticsearch의 주요 기능 : 분산, 고 가용성, 비동기 작문, 멀티 API, 문서 지향.
Elasticsearch Core 개념 : 거의 실시간, 클러스터, 노드 (데이터 저장), 인덱스, 샤드 (슬라이싱 인덱스 파편), 복제품 (슬라이스가 여러 복제본을 설정할 수 있음). 대량의 데이터를 신속하게 저장, 검색 및 분석 할 수 있습니다.
Elasticsearch 사용 사례 : Wikipedia, Stack Overflow, Github 등
SpringBoot는 Elasticsearch를 통합합니다
SpringBoot를 사용하여 Elasticsearch를 통합하기 전에 그들 사이의 관계를 이해해야합니다.
| 스프링 부트 버전 (x) | 스프링 데이터 Elasticsearch 버전 (Y) | Elasticsearch 버전 (Z) |
|---|---|---|
| x <= 1.3.5 | y <= 1.3.4 | z <= 1.7.2* |
| x> = 1.4.x | 2.0.0 <= y <5.0.0 ** | 2.0.0 <= z <5.0.0 ** |
여기서 사용중인 SpringBoot 버전은 1.5.9이며 Elasticsearch 버전은 2.3.5입니다.
SpringBoot를 사용하여 Elasticsearch를 통합하면 일반적으로 SpringData를 사용하여 캡슐화 된 다음 DAO 레이어 인터페이스는 ElasticsearchRepository 클래스를 상속합니다. 이 클래스는 일반적으로 사용되는 CRUD 방법과 같은 많은 방법을 구현합니다.
SpringData 사용
먼저 사용하기 전에 관련 준비를하십시오.
Maven의 구성은 다음과 같습니다.
<pectionency> <groupId> org.springframework.boot </groupid> <artifactid> 스프링-부트 스타터-web </artifactid> <5.9. release </version> </dependency> <groupId> org.spramework.spramework.spramework.spramework.spramed> spring-root-starter-starter-startic-startifactic </rigpactid- <버전> 1.5.9. release </version> </fectionency>
Application.Properties 구성
spring.data.elasticsearch.repositories.enabled = truespring.data.elasticsearch.cluster-nodes = 127.0.0.1/: 9300
참고 : 9300은 Java 클라이언트의 포트입니다. 9200은 편안한 HTTP를 지원하는 인터페이스입니다.
더 많은 구성 :
spring.data.elasticsearch.cluster-name elasticsearch 클러스터 이름. (기본값 : Elasticsearch)
spring.data.elasticsearch.cluster-nodes 클러스터 노드 주소 목록, 쉼표로 구분됩니다. 지정되지 않은 경우 클라이언트 노드를 시작하십시오.
spring.data.elasticsearch.propertie는 클라이언트의 추가 속성을 구성하는 데 사용됩니다.
spring.data.elasticsearch.repositories.enabled elasticsearch 저장소를 활성화합니다. (기본값 : true.)
코드 쓰기
엔티티 클래스
@document (indexname = "userIndex", type = "user") public 클래스 사용자는 직렬화 가능 { / ** * / private static final long serialversionuid = 1l을 구현합니다. / ** 번호*/ 개인 긴 ID; / ** 이름*/ 개인 문자열 이름; / ** 연령*/ 개인 정수 시대; / ** 설명*/ 개인 문자열 설명; / ** 생성 시간*/ 개인 문자열 createTm; // getter and setter 생략}SpringData를 사용하는 경우 Indexname을 설정하고 엔티티 클래스에서 입력해야합니다. 기존 데이터베이스와 비교하면 라이브러리 및 테이블과 같습니다.
인덱스 이름과 유형이 모두 소문자에 있어야한다는 점에 유의해야합니다 !!!
다오 레이어
public interface userdao는 elasticsearchrepository <user, long> {}을 확장합니다.DAO 층은 여기에서 비교적 간단하며 ElasticsearchRepository 클래스를 상속합니다. 주요 방법은 저장, 삭제 및 검색입니다. 저장 메소드는 삽입 및 업데이트와 매우 유사합니다. 없으면 추가되면 추가 될 것이고 하나가 있으면 덮을 것입니다. 삭제 방법은 주로 데이터 및 인덱스 라이브러리를 삭제하는 것입니다. 검색과 관련하여, 이는 페이지 매김, 무게 등과 같은 일반적으로 사용되는 일부 쿼리를 포함한 쿼리입니다.
서비스 계층
@ServicePublic Class usererViceimpl은 userErvice {@autowired private userdao userdao; @override public boolean insert (사용자 사용자) {boolean falg = false; try {userdao.save (user); falg = true; } catch (예외 e) {e.printstacktrace (); } return falg; } @override public list <user> search (string searchContent) {QueryStringQueryBuilder builder = new QueryStringQueryBuilder (SearchContent); System.out.println ( "쿼리 문 :"+builder); 반복 가능한 <user> searchResult = userDao.search (builder); iterator <user> iterator = searchResult.iterator (); List <user> list = new ArrayList <user> (); while (iterator.hasnext ()) {list.add (iterator.next ()); } 반환 목록; } @override public list <user> searchUser (정수 pagenumber, 정수 pageize, string searchContent) {// Pagination 매개 변수 pagable = new PageRequest (pagenumber, pagesize); QueryStringQueryBuilder Builder = New QueryStringQueryBuilder (SearchContent); SearchQuery SearchQuery = New NativeSearchQueryBuilder (). WithPagable (pagable) .withQuery (builder) .build (); System.out.println ( "쿼리 문 :" + searchQuery.getQuery (). toString ()); page <user> searchPageresults = userDao.search (searchQuery); return searchPageresults.getContent (); } @override public list <user> searchUserByweight (string searchContent) {// Query weights functionscorequiller functionscorequeryBuilder = QueryBuilders.functionsCoreQuery () .add (QueryBuilders.boolquery (). scoreFunctionBuilders.weightFactorFunction (10)) .add (QueryBuilders.boolquery ().해야 할 (QueryBuilders.MatchQuery ( "Description", SearchContent)), ScoreFunctionBuilders.weightFactorFunction (100). SetMinsCore (2); System.out.println ( "쿼리 문 :" + functionscorequeryBuilder.toString ()); 반복 가능한 <user> searchResult = userDao.search (functionsCoreQueryBuilder); iterator <user> iterator = searchResult.iterator (); List <user> list = new ArrayList <user> (); while (iterator.hasnext ()) {list.add (iterator.next ()); } 반환 목록; }}여기서 나는 단순히 몇 가지 방법을 작성했습니다. 주요 방법은 쿼리입니다. 쿼리에는 전체 텍스트 검색, 페이지 매김 쿼리 및 가중치 쿼리가 포함됩니다. 설명해야 할 것은 가중치 쿼리입니다. 무게 점수가 높을수록 쿼리 결과가 높아집니다. 다른 데이터에 대해 점수가 설정되지 않은 경우 기본 점수는 1입니다.이 문장을 쿼리하지 않으려면 SetMinscore를 사용하여 1 이상으로 설정하십시오.
코드 테스트
인터페이스를 호출하여 데이터를 추가하십시오
새로운 데이터 :
post http : // localhost : 8086/api/user { "id": 1, "name": "Zhang San", "Age": 20, "Description": "Zhang San은 Java 개발 엔지니어", "CreateTm": "2018-4-25 11:07:42"} { "id": "li si", ",", ",", ",", ",", "2,", "2,", ":", ":", ",": ",": ":", ":", ":", ":" SI는 테스트 엔지니어 ","CreateTM ":"1980-2-15 19:01:32 "} {"ID ": 3,"Name ":"Wang Wu ","Age ": 25,"Description ":"Wang Wu는 운영 및 유지 보수 엔지니어 ","CreateTM ":"2016-8-21 06:11:32 "}입니다. 전체 텍스트 쿼리를 수행하십시오
묻다
http : // localhost : 8086/api/user? searchContent = 엔지니어
반품
[{ "id": 2, "name": "li si", "age": 14, "description": "Li Si는 테스트 엔지니어", "CreateTM": "1980-2-15 19:01:32"}, { "ID": "이름": "Zhang San", "Age": 20, "Description": "Zhang San": "Zhang San": "2018-4-25 11:07:42"}, { "id": 3, "name": "Wang Wu", "Age": 25, "Description": "Wang Wu는 작동 및 유지 보수 엔지니어", "CreateTM": "2016-8-21 06:11:32"}] 페이지 매김 쿼리를 수행하십시오
묻다
http : // localhost : 8086/api/user? pagenumber = 0 & pagesize = 2 & searchContent = 엔지니어
반품
[{ "id": 2, "name": "li si", "age": 14, "description": "li si는 테스트 엔지니어입니다"}, { "id": "name": "Zhang San", "Age": 20, "Description": "Zhang San은 Java Development Engineer"}] 무게 쿼리를 수행하십시오
묻다
http : // localhost : 8086/api/user2? searchContent = li si
반품
[{ "id": 2, "name": "li si", "age": 24, "description": "li si는 테스트 엔지니어", "CreateTm": "1980-2-15 19:01:32"}]가중치 쿼리 프린트 문 :
Query 문 : {{ "function_score": { "functions": [{ "필터": { "bool": { "bool": { "dour": { "match": { "query": "li si", "type": "boolean"}}}}}}}}}}}}}}}}}}}}}}}}} { "bool": { "dour": { "match": { "descrip": { "query": "li si", "type": "boolean"}}}}}}}}}}, "weight": 100.0}], "min_score": 2.0}}참고 : 테스트에서 SetMinscore의 최소 중량이 2로 나뉘어 지므로 관련없는 데이터가 표시되지 않습니다. 표시하려면 코드에서 제거하십시오.
새 데이터를 추가 한 후 http : // localhost : 9200/_plugin/head/in the browser를 입력 할 수 있습니다.
그런 다음 기본 쿼리를 클릭하여 추가 된 데이터를보십시오. 명령문 쿼리를 사용하려면 프로그램의 콘솔에서 인쇄 한 쿼리 명령문을 쿼리 인터페이스에 붙여 넣을 수 있습니다!
참고 : 여기에 Windows에 Elasticsearch를 설치하고 ES 플러그인 헤드를 설치했습니다. 특정 설치 단계는 기사의 끝에 있습니다.
SpringData 외에도 실제로 Elasticsearch를 작동하는 다른 방법이 있습니다.
예를 들어, Native Elasticsearch API를 사용하여 TransportClient 클래스를 사용하여 구현하십시오.
또는 스프링으로 캡슐화하는 데 사용하여 서비스 계층에 Bean을 주입하십시오.
예:
@autowired elasticsearchtemplate elasticsearchtemplate;
그러나 위의 방법에는 한계가 있습니다. 즉, Elasticsearch 버전이 변경됨에 따라 관련 Java API도 지속적으로 조정됩니다.
따라서 매우 유용한 타사 도구 제스트 클리어를 소개합니다. Elasticsearch를 캡슐화하고 Elasticsearch httprest 인터페이스 클라이언트의 간격을 채 웁니다. Elasticsearch 2.x 이상의 버전에 적합하며 Elasticsearch 서버 버전 변경으로 인해 코드를 변경할 필요가 없습니다!
사전
먼저 Maven에 다음의 종속성을 추가하십시오.
<pectionency> <groupid> io.searchbox </groupid> <artifactid> jest </artifactid> <bersion> 5.3.3 </version> </dependency>
그런 다음 관련 테스트 코드를 작성하십시오.
코드의 의견은 매우 완전해야하므로 여기서 코드에 대해 너무 많이 이야기하지 않을 것입니다.
import java.util.arraylist; import java.util.list; import org.elasticsearch.query.query.querybuilders; import org.elasticsearch.search.builder.searchsourcebuilder; import com.pancm.pojo.user; import io.searchbox.cleient.jestclient; io.searchbox.client.jestclientFactory; import io.searchbox.client.jestresult; import io.searchbox.client.config.httpclientconfig; import io.searchbox.core.bulk; import io.searchbox.core.bulkresult; import io.searchbox.core.delete; io.searchbox.core.documentresult; import io.searchbox.core.index; import io.searchbox.core.search; import io.searchbox.indices.createindex; import io.searchbox.indices.deleteIndex; import io.searchbox.indices.mapping.getmapping; incearch.search box.sportmapping; Jesttest {private static Jestclient Jestclient; private static string indexname = "userIndex"; // private static string indexname = "userIndex2"; 개인 정적 문자열 typename = "사용자"; 개인 정적 문자열 elasticips = "http://192.169.2.98:9200"; // private static string elasticips = "http://127.0.1:9200"; public static void main (string [] args)은 예외 {jestclient = getjestclient (); insertbatch (); sarach1 (); sarach2 (); sarach3 (); Jestclient.close (); } private static jestclient getJestClient () {jestclientFactory factory = new JestClientFactory (); Factory.sethttpclientConfig (new httpclientConfig.builder (elasticips) .conntimeout (60000) .ReadTimeout (60000) .multThreaded (true) .build ()); return factory.getObject (); } public static void insertbatch () {list <boodge> objs = new ArrayList <Object> (); objs.add (새로운 사용자 (1L, "Zhang San", 20, "Zhang San은 Java Development Engineer", "2018-4-25 11:07:42")); objs.add (새로운 사용자 (2L, "li si", 24, "li si는 테스트 엔지니어", "1980-2-15 19:01:32")); objs.add (새로운 사용자 (3L, "Wang Wu", 25, "Wang Wu는 운영 및 유지 보수 엔지니어", "2016-8-21 06:11:32")); 부울 결과 = 거짓; try {result = insertbatch (jestclient, indexname, typeName, objs); } catch (예외 e) {e.printstacktrace (); } system.out.println ( "Batch new :"+result); } / *** 전체 텍스트 검색* / public static void sarach1 () {String query = "엔지니어"; {SearchSourceBuilder SearchSourceBuilder = New SearchSourceBuilder (); SearchSourceBuilder.query (QueryBuilders.QueryStringQuery (Query)); // 페이지 설정 SearchSourceBuilder.from (0) .Size (2); System.out.println ( "Full-Text Search Query 문 :"+SearchSourceBuilder.toString ()); System.out.println ( "전체 텍스트 검색 리턴 결과 결과 :"+검색 (Jestclient, IndexName, TypeName, SearchSourceBuilder.toSourceBuilder.tostring ())); } catch (예외 e) {e.printstacktrace (); }} / *** 정확한 검색* / public static void sarach2 () {try {searchSourceBuilder searchSourceBuilder = new SearchSourceBuilder (); SearchSourceBuilder.query (QueryBuilders.ermquery ( "Age", 24)); System.out.println ( "정확한 검색 쿼리 문 :"+SearchSourceBuilder.toString ()); System.out.println ( "정확한 검색 리턴 결과 결과 :"+검색 (Jestclient, Indexname, typeName, searchSourceBuilder.toString ())); } catch (예외 e) {e.printstacktrace (); }} / *** 간격 검색* / public static void sarach3 () {String CreateTm = "createTm"; 문자열 = "2016-8-21 06:11:32"; 문자열 to = "2018-8-21 06:11:32"; {SearchSourceBuilder SearchSourceBuilder = New SearchSourceBuilder (); SearchSourceBuilder.query (QueryBuilders.rangeQuery (createTm) .gte (from) .lte (to)); System.out.println ( "간격 검색 문 :"+SearchSourceBuilder.toString ()); System.out.println ( "간격 검색 리턴 결과 :"+search (Jestclient, Indexname, typeName, searchSourceBuilder.tostring ())); } catch (예외 e) {e.printstacktrace (); }} / ** * 생성 색인 * @param indexname * @return * @throws 예외 * / public boolean createIndex (jestclient jestclient, String Indexname)는 예외 {jestresult jr = jestclient.executte (new createIndex.builder (indexname) .Build ()); return jr.issuceeded (); } / ** * 새 데이터 * @param indexname * @param typename * @param source * @return * @throws 예외 * / public boolean insert (Jestclient Jestclient, String Indexname, String Typename, String Source) 예외 {putmapping putmapping = new PutMapping.builder (Indexname, typename, source). jestresult jr = jestclient.execute (putmapping); return jr.issuceeded (); } / ** * query data * @param indexname * @param typename * @return * @throws exception * / public static string getIndexMapping (JestClient JestClient, String Indexname, String Typename)은 예외 {getMapping getMapping = new getMapping.builder () .AdDexam (indexname). jestresult jr = jestclient.execute (getmapping); return jr.getJsonstring (); } / ** * 배치로 데이터 추가 * @param indexname * @param typename * @param objs * @return * @throws 예외 * / public static boolean insertbatch (Jestclient Jestclient, String Indexname, String typename, list <bood> objs) 예외 {bulk.builder bulk = new bulk.builder (). defaultIndex (indexname) .defaultType (typeName); for (object obj : objs) {index index = new index.builder (obj) .build (); BULK.ADDACTION (색인); } bulkresult br = jestclient.execute (bulk.build ()); return br.issuceeded (); } / ** * 전체 텍스트 검색 * @param indexname * @param typename * @param query * @return * @throws 예외 * / public static string search (Jestclient Jestclient, String Indexname, String Typename, String Query) 예외 {search search = new search.builder (Query) (indexname). jestresult jr = jestclient.execute (검색); // system.out.println ( "-"+jr.getJsonstring ()); // system.out.println ( "-"+jr.getSourceAsObject (user.class)); return jr.getsourceasstring (); } / ** * 삭제 삭제 * @param indexname * @return * @Throws Exception * / public boolean delete (JestClient Jestclient, String Indexname) 예외 {jestresult jr = jestclient.executte (new deleteindex.builder (indexname) .build ()); return jr.issuceeded (); } / ** * 데이터 삭제 * @param indexname * @param typename * @param id * @return * @throws 예외 * / public boolean delete (jestclient jestclient, string indexname, 문자열 타이프 이름, 문자열 ID)는 예외 {documentresult dr = jestclient.execute (new delete.builder (id) .index (indexname) .type (typename) .build ()); 반환 dr.Issuceeded (); }참고 : 테스트하기 전에 먼저 로컬 Windows 시스템에 설치된 Elasticsearch 버전은 2.3.5이며 Linux 서버에 설치된 Elasticsearch 버전은 6.2입니다.
테스트 결과
전문 검색
전체 텍스트 검색 쿼리 문 : { "from": 0, "size": 2, "query": { "query_string": { "query_string": {엔지니어 "}}} 전체 텍스트 검색 결과를 반환합니다. {"ID ": 1,"이름 ":"Zhang San ","Age ":"Description ":"Zhang San " 엔지니어 ","CreateTM ":"2018-4-25 11:07:42 "}, {"id ": 2,"name ":"li si ","li si ","age ": 24,"description ":"Li Si는 테스트 엔지니어 ","CreateTM ":"1980-2-15 19:01:32 "}일치 검색
정확한 검색 쿼리 문 : { "query": { "term": { "age": 24}}} 정확한 검색 결과 : { "id": 2, "name": "li si", "age": 24, "description": "li si는 테스트 엔지니어", "CreateTm": "1980-2-15 19:32"}}}}}}시간 간격 검색
간격 검색 문 : { "query": { "범위": { "createTM": { "from": "2016-8-21 06:11:32", "to": "2018-8-21 06:11:32", "includ_lower": true, "include_upper": true}}} interval 검색 반품 결과 : { "id": ""id ": San ","Age ": 20,"Description ":"Zhang San은 Java Development Engineer ","CreateTM ":"2018-4-25 11:07:42 "}새 데이터를 추가 한 후 Linux Kibana로 이동하여 관련 쿼리를 수행 할 수 있으며 쿼리 결과는 다음과 같습니다.
참고 : Kibana는 ELK의 오픈 소스 소프트웨어입니다. Kibana는 Logstash 및 Elasticsearch에 대한 로그 분석 친화적 인 웹 인터페이스를 제공하여 중요한 데이터 로그를 요약, 분석 및 검색하는 데 도움이됩니다.
위 코드에서 테스트에 의해 반환 된 결과는 우리의 기대와 일치합니다. 그중에는 Jestclient의 작은 부분 만 사용됩니다. 자세한 내용은 Jestclient의 공식 문서를 확인할 수 있습니다.
Windows에 Elasticsearch를 설치하십시오
1. 문서 준비
다운로드 주소 : https://www.elastic.co/downloads
Elasticsearch 관련 버전을 선택한 다음 접미사 이름 zip 파일을 선택하여 다운로드 한 다음 다운로드 한 후 압축을 풀어주십시오.
2. Elasticsearch를 시작하십시오
빈 디렉토리로 이동하여 elasticsearch.bat 실행하십시오
다음을 입력하십시오 : LocalHost : 9200 찾아보기
인터페이스를 성공적으로 표시한다는 것은 성공을 의미합니다!
3. ES 플러그인을 설치하십시오
웹 관리 인터페이스 헤드 설치
빈 디렉토리를 입력하고 CMD를 열고 DOS 인터페이스를 입력하십시오.
입력 : plugin install mobz/elasticsearch-head
다운로드하십시오
성공적인 다운로드 후 : http : // localhost : 9200/_plugin/head/
인터페이스가 표시되면 설치가 성공적입니다!
4. 등록 서비스
빈 디렉토리를 입력하고 CMD를 열고 DOS 인터페이스를 입력하십시오.
입력하다:
service.bat installservice.bat start
성공 후 입력하십시오
Services.msc
ES의 실행 상태를 직접 볼 수 있도록 서비스 서비스 인터페이스로 이동하십시오!
다른
Elasticsearch 공식 웹 사이트 API 주소 :
https://www.elastic.co/guide/en/elasticsearch/client/java-api/2.3/index.html
JestclientGithub 주소 :
https://github.com/searchbox-io/jest (로컬 다운로드)
나는 프로젝트를 Github에 올렸다.
https://github.com/xuwujing/springboot (로컬 다운로드)
요약
위는이 기사의 전체 내용입니다. 이 기사의 내용에 모든 사람의 연구 나 작업에 대한 특정 참조 가치가 있기를 바랍니다. 궁금한 점이 있으면 의사 소통을 위해 메시지를 남길 수 있습니다. Wulin.com을 지원 해주셔서 감사합니다.