gpt4 book ai didi

Spring Boot集成ElasticSearch实现搜索引擎的示例

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 32 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章Spring Boot集成ElasticSearch实现搜索引擎的示例由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

elastic search是一个开源的,分布式,实时搜索和分析引擎。spring boot为elasticsearch及spring data elasticsearch提供的基于它的抽象提供了基本的配置。spring boot提供了一个用于聚集依赖的spring-boot-starter-data-elasticsearch 'starterpom'.

elasticsearch作为搜索引擎,我们需要解决2大问题:

1,  如何将被搜索的数据在es上创建反向索引 2,  java代码如何与es交互 。

其中第一个大问题又分为两个小问题 。

1.1,如何初始化已有的数据 1.2,如何同步增量数据 。

第二个大问题也有两种集成方式 。

2.1 spring data 9300端口集成 2.2 restful api 9200端口集成 。

本篇先解决第二大问题.

第一种方式,利用restapi方式,也叫jest方式:

示例代码:https://github.com/yejingtao/forblog/tree/master/demo-jest-elasticsearch 。

pom.xml:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<project xmlns= "http://maven.apache.org/pom/4.0.0" xmlns:xsi= "http://www.w3.org/2001/xmlschema-instance"
  xsi:schemalocation= "http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
  <modelversion> 4.0 . 0 </modelversion>
 
  <groupid>yejingtao.demo.springcloud</groupid>
  <artifactid>demo-jest-elasticsearch</artifactid>
  <version> 0.0 . 1 -snapshot</version>
  <packaging>jar</packaging>
 
  <name>demo-jest-elasticsearch</name>
  <url>http: //maven.apache.org</url>
 
  <properties>
   <project.build.sourceencoding>utf- 8 </project.build.sourceencoding>
  </properties>
  
  <parent>
     <groupid>org.springframework.boot</groupid>
     <artifactid>spring-boot-starter-parent</artifactid>
     <version> 1.5 . 6 .release</version>
   </parent>
   
   <dependencies>
     <dependency>
       <groupid>org.springframework.boot</groupid>
       <artifactid>spring-boot-starter-web</artifactid>
     </dependency>
     <dependency>
       <groupid>org.springframework.boot</groupid>
       <artifactid>spring-boot-starter-data-elasticsearch</artifactid>
     </dependency>
     <dependency>
       <groupid>io.searchbox</groupid>
       <artifactid>jest</artifactid>
     </dependency>
     <dependency>
       <groupid>net.java.dev.jna</groupid>
       <artifactid>jna</artifactid>
     </dependency>
   </dependencies>
</project>

application.yml

?
1
2
3
4
5
6
7
8
9
server:
  port: 7081
 
spring:
  elasticsearch:
   jest:
    uris:
    - http: //192.168.226.133:9200
    read-timeout: 5000

注意这里是9200端口 。

主程序:最简单的spring boot启动程序:

?
1
2
3
4
5
6
7
@springbootapplication
public class esapplication {
 
   public static void main(string[] args) {
     springapplication.run(esapplication. class );
   }
}

定义好es中的实体类和对es操作的接口:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class entity implements serializable{
 
   private static final long serialversionuid = -763638353551774166l;
   
   public static final string index_name = "index_entity" ;
   
   public static final string type = "tstype" ;
 
   private long id;
   
   private string name;
   
   public entity() {
     super ();
   }
   
   public entity( long id, string name) {
     this .id = id;
     this .name = name;
   }
 
   public long getid() {
     return id;
   }
 
   public void setid( long id) {
     this .id = id;
   }
 
   public string getname() {
     return name;
   }
 
   public void setname(string name) {
     this .name = name;
   }
   
   
}
?
1
2
3
4
5
6
7
8
public interface cityesservice {
   
   void saveentity(entity entity);
   
   void saveentity(list<entity> entitylist);
   
   list<entity> searchentity(string searchcontent);
}

接口实现:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
@service
public class cityesserviceimpl implements cityesservice{
   
   private static final logger logger = loggerfactory.getlogger(cityesserviceimpl. class );
   
   @autowired
   private jestclient jestclient;
   
   @override
   public void saveentity(entity entity) {
     index index = new index.builder(entity).index(entity.index_name).type(entity.type).build();
     try {
       jestclient.execute(index);
       logger.info( "es 插入完成" );
     } catch (ioexception e) {
       e.printstacktrace();
       logger.error(e.getmessage());
     }
   }
   
   
   /**
    * 批量保存内容到es
    */
   @override
   public void saveentity(list<entity> entitylist) {
     bulk.builder bulk = new bulk.builder();
     for (entity entity : entitylist) {
       index index = new index.builder(entity).index(entity.index_name).type(entity.type).build();
       bulk.addaction(index);
     }    
     try {
       jestclient.execute(bulk.build());
       logger.info( "es 插入完成" );
     } catch (ioexception e) {
       e.printstacktrace();
       logger.error(e.getmessage());
     }
   }
   
   /**
    * 在es中搜索内容
    */
   @override
   public list<entity> searchentity(string searchcontent){
     searchsourcebuilder searchsourcebuilder = new searchsourcebuilder();
     //searchsourcebuilder.query(querybuilders.querystringquery(searchcontent));
     //searchsourcebuilder.field("name");
     searchsourcebuilder.query(querybuilders.matchquery( "name" ,searchcontent));
     search search = new search.builder(searchsourcebuilder.tostring())
         .addindex(entity.index_name).addtype(entity.type).build();
     try {
       jestresult result = jestclient.execute(search);
       return result.getsourceasobjectlist(entity. class );
     } catch (ioexception e) {
       logger.error(e.getmessage());
       e.printstacktrace();
     }
     return null ;    
   }
}

这里插入数据的方式给了两种,一种是单次api直接插入,一种是利用es的bulk批量插入.

做一个controller方面我们测试:

启动后在浏览器中请求http://localhost:7081/entitycontroller/search?name=%e4%ba%ba%e6%89%8b%e4%ba%95 。

得到结果:

Spring Boot集成ElasticSearch实现搜索引擎的示例

这里只返回了9条记录,而理论上es默认的size是10,应该不是分页的问题,而是只能检索出9条匹配记录,用kibana连上相同的搜索确认下:

Spring Boot集成ElasticSearch实现搜索引擎的示例

这里用的是standard分词方式,将每个中文都作为了一个term,凡是包含“人”“手”“井”的都被搜索了出来,只是评分不同,如果想支持只能中文索引需要依赖ik插件 。

ok,restful方式对elasticsearch的检索已经搞定了,更多的扩展可以慢慢研究下querybuilders里的源码和批注.

第二种方式,利用spring data客户端方式:

事先说明此方式有个弊端,让我掉了坑里好久才爬上来,spring data elasticsearch必须与elasticsearch版本相匹配,否则在对接时es端会报版本不匹配错误,例如我es是5.6.1版本,spring boot是1.5.6版本,错误如下:

为解决这个问题我查找了一些资料,spring data与elasticsearch版本对应关系如下:

  。

spring data elasticsearch 。

elasticsearch 。

3.0.0.rc2 。

5.5.0 。

3.0.0.m4 。

5.4.0 。

2.0.4.release 。

2.4.0 。

2.0.0.release 。

2.2.0 。

1.4.0.m1 。

1.7.3 。

1.3.0.release 。

1.5.2 。

1.2.0.release 。

1.4.4 。

1.1.0.release 。

1.3.2 。

1.0.0.release 。

1.1.1 。

  。

而我用的spring boot 1.5.6版本对应的spring data elasticsearch是2.1.6版本,不支持5.x的es,所以报错。到本博文撰写为止,spring boot的release版本最新的是1.5.8,对应的spring data elasticsearch是2.1.8,仍不支持5.x的es,所以如果一定要使用java客户端方式集成es只能放弃spring boot直接使用spring data和spring mvc,或者降低es的版本使之与spring boot匹配.

示例代码:https://github.com/yejingtao/forblog/tree/master/demo-data-elasticsearch 。

pom.xml依赖:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<project xmlns= "http://maven.apache.org/pom/4.0.0" xmlns:xsi= "http://www.w3.org/2001/xmlschema-instance"
  xsi:schemalocation= "http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
  <modelversion> 4.0 . 0 </modelversion>
 
  <groupid>yejingtao.demo.springcloud</groupid>
  <artifactid>demo-data-elasticsearch</artifactid>
  <version> 0.0 . 1 -snapshot</version>
  <packaging>jar</packaging>
 
  <name>demo-data-elasticsearch</name>
  <url>http: //maven.apache.org</url>
 
  <properties>
   <project.build.sourceencoding>utf- 8 </project.build.sourceencoding>
  </properties>
  
  <parent>
     <groupid>org.springframework.boot</groupid>
     <artifactid>spring-boot-starter-parent</artifactid>
     <version> 1.5 . 8 .release</version>
   </parent>
   
   <dependencies>
     <dependency>
       <groupid>org.springframework.boot</groupid>
       <artifactid>spring-boot-starter-web</artifactid>
     </dependency>
     <dependency>
       <groupid>org.springframework.boot</groupid>
       <artifactid>spring-boot-starter-data-elasticsearch</artifactid>
     </dependency>
   </dependencies>
</project>

不再引用jest.

application.yml

?
1
2
3
4
5
6
7
8
9
10
server:
  port: 7081
 
spring:
  data:
   elasticsearch:
    cluster-nodes: 192.168 . 226.133 : 9300
    cluster-name: my-es
    repositories:
     enabled: true

注意这里是9300端口 。

controller、主程序、service接口同jest项目不变,不再罗列 。

实体类稍作变化,指定es中的index和type:

?
1
@document (indexname= "index_entity" , type= "tstype" )

多一个repository接口,无需实现类,spring data标准用法:

?
1
2
3
4
5
6
7
8
/**
  * entity es操作类
  * @author yejingtao
  *
  */
public interface entityrepository extends elasticsearchrepository<entity, long >{
 
}

service实现类与jest的天壤之别了,从语法上可以看出更像是对数据库层的操作:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
@service
public class cityesserviceimpl implements cityesservice{
   
   private static final logger logger = loggerfactory.getlogger(cityesserviceimpl. class );
   
   int page_size = 15 ; //默认分页大小
   
   int page_number = 0 ; //默认当前分页
   
   string score_mode_sum = "sum" ; //权重分求和模式
   
   float min_score = 10 .0f; //由于无相关性的分值默认为1, 设置权重分最小值为10
   
   @autowired
   entityrepository entityrepository;
   
   /**
    * 保存内容到es
    */
   @override
   public long saveentity(entity entity) {
     entity entityresult = entityrepository.save(entity);
     return entityresult.getid();
   }
   
   /**
    * 在es中搜索内容
    */
   @override
   public list<entity> searchentity( int pagenumber, int pagesize, string searchcontent){
     if (pagesize== 0 ) {
       pagesize = page_size;
     }
     if (pagenumber< 0 ) {
       pagenumber = page_number;
     }
     
     searchquery searchquery = getentitysearchquery(pagenumber,pagesize,searchcontent);
     
     logger.info( "\n searchcity: searchcontent [" + searchcontent + "] \n dsl = \n "
         + searchquery.getquery().tostring());
 
     
     page<entity> citypage = entityrepository.search(searchquery);
     return citypage.getcontent();
   }
   
   /**
    * 组装搜索query对象
    * @param pagenumber
    * @param pagesize
    * @param searchcontent
    * @return
    */
   private searchquery getentitysearchquery( int pagenumber, int pagesize, string searchcontent) {
     functionscorequerybuilder functionscorequerybuilder = querybuilders.functionscorequery()
         .add(querybuilders.matchphrasequery( "name" , searchcontent),
             scorefunctionbuilders.weightfactorfunction( 1000 ))
         //.add(querybuilders.matchphrasequery("other", searchcontent),
             //scorefunctionbuilders.weightfactorfunction(1000))
         .scoremode(score_mode_sum).setminscore(min_score);
     //设置分页,否则只能按照es默认的分页给
     pageable pageable = new pagerequest(pagenumber, pagesize);
     return new nativesearchquerybuilder().withpageable(pageable).withquery(functionscorequerybuilder).build();
   }
   
}

测试方式同jest.

这两种方式,从设计上来讲属于两种思路,spring data的思路就是将elasticsearch当自家的数据仓库来管理,直接通过java客户端代码操作es;jest的思路是将elasticsearch当为独立的服务端,自己作为客户端用兼容性最强的restful格式来与之交互。 个人比较倾向于jest方式,第一兼容性好,不需要考虑版本的问题。第二,从elasticsearch本身的设计上来分析,9200是对外服务端口,9300是内部管理和集群通信端口,请求9200获取搜索服务更符合es的设计初衷,不会影响集群内部的通信。 以上比较分析仅代表个人观点,欢迎大神么交流批评。希望对大家的学习有所帮助,也希望大家多多支持我.

原文链接:http://blog.csdn.net/yejingtao703/article/details/78414874 。

最后此篇关于Spring Boot集成ElasticSearch实现搜索引擎的示例的文章就讲到这里了,如果你想了解更多关于Spring Boot集成ElasticSearch实现搜索引擎的示例的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com