V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hansonwang99
V2EX  ›  Blogger

自制一个 elasticsearch-spring-boot-starter

  •  
  •   hansonwang99 · 2019-02-28 08:23:14 +08:00 · 1740 次点击
    这是一个创建于 2124 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Samsung Galaxy S10


    概 述

    Elasticsearch 在企业里落地的场景越来越多了,但是大家在项目里使用 Elasticsearch 的姿势也是千奇百怪,这次正好自己需要使用,所以干脆就封装一个 elasticsearch-spring-boot-starter 以供复用好了。如果不知道 spring-boot-starter 该如何制作,可以参考文章《如何自制一个 Spring Boot Starter 并推送到远端公服》,下面就来简述一下自制的 elasticsearch-spring-boot-starter 该如何使用。


    依赖引入

    <dependency>
    	<groupId>com.github.hansonwang99</groupId>
    	<artifactId>elasticsearch-spring-boot-starter</artifactId>
    	<version>0.0.8</version>
    </dependency>
    
    <repositories>
    	<repository>
    		<id>jitpack.io</id>
    		<url>https://jitpack.io</url>
    	</repository>
    </repositories>
    

    配置文件

    如果你还没有一个属于自己的 Elasticsearch 集群,可以参考文章 《 CentOS7 上搭建多节点 Elasticsearch 集群》来一步步搭建之,本文实验所用的集群即来源于此。

    elasticsearch:
      host: 192.168.31.75
      httpPort: 9200
      tcpPort: 9300
      clusterName: codesheep
      docFields: title,filecontent
      auth:
        enable: false
    

    各个字段解释如下:

    • host:Elasticsearch 节点地址
    • httpPort: Elasticsearch REST 端口
    • tcpPort:Elasticsearch TCP 端口
    • clusterName:集群名
    • docFields:文档字段,以英文逗号间隔,比如我这里的业务场景是文档包含 标题( title )内容( filecontent )字段
    • auth:是否需要权限认证

    由于我这里安装的实验集群并无 x-pack权限认证的加持,因此无需权限认证,实际使用的集群或者阿里云上的 Elasticsearch 集群均有完善的 x-pack权限认证,此时可以加上用户名 /密码的配置:

    elasticsearch:
      host: 192.168.199.75
      httpPort: 9200
      tcpPort: 9300
      clusterName: codesheep
      docFields: title,filecontent
      auth:
        enable: true
        username: elasticsearch
        password: xxxxxx
    

    用法例析

    • 首先注入相关资源
    @Autowired
    private ISearchService iSearchService;
    
    @Autowired
    private DocModel docModel;
    

    这些都是在 elasticsearch-spring-boot-starter 中定义的

    • 创建索引
    public String createIndex() throws IOException {
    
    	IndexModel indexModel = new IndexModel();
    	indexModel.setIndexName("testindex2"); // 注意索引名字必须小写,否则 ES 抛异常
    	indexModel.setTypeName("testtype2");
    	indexModel.setReplicaNumber( 2 );   // 两个节点,因此两个副本
    	indexModel.setShardNumber( 3 );
    
    	XContentBuilder builder = null;
    	builder = XContentFactory.jsonBuilder();
    	builder.startObject();
    	{
    		builder.startObject("properties");
    		{
    			builder.startObject("title");
    			{
    				builder.field("type", "text");
    				builder.field("analyzer", "ik_max_word");
    			}
    			builder.endObject();
    			builder.startObject("filecontent");
    			{
    				builder.field("type", "text");
    				builder.field("analyzer", "ik_max_word");
    				builder.field("term_vector", "with_positions_offsets");
    			}
    			builder.endObject();
    		}
    		builder.endObject();
    	}
    	builder.endObject();
    
    	indexModel.setBuilder( builder );
    	Boolean res = iSearchService.createIndex(indexModel);
    
    	if( true==res )
    		return "创建索引成功";
    	else
    		return "创建索引失败";
    }
    
    • 删除索引
    public String deleteIndex() {
    	return (iSearchService.deleteIndex("testindex2")==true) ? "删除索引成功":"删除索引失败";
    }
    
    • 判断索引是否存在
    if ( existIndex(indexName) ) {
    	...
    } else {
    	...
    }
    
    • 插入单个文档
    public String insertSingleDoc( ) {
    	SingleDoc singleDoc = new SingleDoc();
    	singleDoc.setIndexName("testindex2");
    	singleDoc.setTypeName("testtype2");
    	
    	Map<String,Object> doc = new HashMap<>();
        doc.put("title","人工智能标题 1");
        doc.put("filecontent","人工智能内容 1");
    	singleDoc.setDocMap(doc);
    	
    	return ( true== iSearchService.insertDoc( singleDoc ) ) ? "插入单个文档成功" : "插入单个文档失败";
    }
    
    • 批量插入文档
    public String insertDocBatch() {
    
    	BatchDoc batchDoc = new BatchDoc();
    	batchDoc.setIndexName("testindex2");
    	batchDoc.setTypeName("testtype2");
    
    	Map<String,Object> doc1 = new HashMap<>();
    	doc1.put("title","人工智能标题 1");
    	doc1.put("filecontent","人工智能内容 1");
    	Map<String,Object> doc2 = new HashMap<>();
    	doc2.put("title","人工智能标题 2");
    	doc2.put("filecontent","人工智能内容 2");
    	Map<String,Object> doc3 = new HashMap<>();
    	doc3.put("title","人工智能标题 3");
    	doc3.put("filecontent","人工智能内容 3");
    	Map<String,Object> doc4 = new HashMap<>();
    	doc4.put("title","人工智能标题 4");
    	doc4.put("filecontent","人工智能内容 4");
    
    	List<Map<String,Object>> docList = new ArrayList<>();
    	docList.add( doc1 );
    	docList.add( doc2 );
    	docList.add( doc3 );
    	docList.add( doc4 );
    
    	batchDoc.setBatchDocMap( docList );
    
    	return ( true== iSearchService.insertDocBatch( batchDoc ) ) ? "批量插入文档成功" : "批量插入文档失败";
    }
    
    • 搜索文档
    public List<Map<String,Object>> searchDoc() {
    
    	SearchModel searchModel = new SearchModel();
    	searchModel.setIndexName( "testindex2" );
    	List<String> fields = new ArrayList<>();
    	fields.add("title");
    	fields.add("filecontent");
    	fields.add("id");
    	searchModel.setFields( fields );
    	searchModel.setKeyword( "人工" );
    	searchModel.setPageNum( 1 );
    	searchModel.setPageSize( 5 );
    
    	return iSearchService.queryDocs( searchModel );
    }
    
    • 删除文档
    public String deleteDoc() {
    	SingleDoc singleDoc = new SingleDoc();
    	singleDoc.setIndexName("testindex2");
    	singleDoc.setTypeName("testtype2");
    	singleDoc.setId("vPHMY2cBcGZ3je_1EgIM");
    	return (true== iSearchService.deleteDoc(singleDoc)) ? "删除文档成功" : "删除文档失败";
    }
    
    • 批量删除文档
    public String deleteDocBatch() {
    	BatchDoc batchDoc = new BatchDoc();
    	batchDoc.setIndexName("testindex2");
    	batchDoc.setTypeName("testtype2");
    	List<String> ids = new ArrayList<>();
    	ids.add("vfHMY2cBcGZ3je_1EgIM");
    	ids.add("vvHMY2cBcGZ3je_1EgIM");
    	batchDoc.setDocIds( ids );
    	return ( true== iSearchService.deleteDocBatch(batchDoc) ) ? "批量删除文档成功" : "批量删除文档失败";
    }
    
    • 更新文档
    public String updateDoc( @RequestBody SingleDoc singleDoc ) {
    
    	SingleDoc singleDoc = new SingleDoc();
    	singleDoc.setId("wPH6Y2cBcGZ3je_1OwI7");
    	singleDoc.setIndexName("testindex2");
    	singleDoc.setTypeName("testtype2");
    	
    	Map<String,Object> doc = new HashMap<>();
        doc.put("title","人工智能标题(更新后)");
        doc.put("filecontent","人工智能内容(更新后)");
    	singleDoc.setUpdateDocMap(doc);
    
    	return (true== iSearchService.updateDoc(singleDoc)) ? "更新文档成功" : "更新文档失败";
    }
    

    后 记

    由于能力有限,若有错误或者不当之处,还请大家批评指正,一起学习交流!



    4 条回复    2019-02-28 17:48:54 +08:00
    hansonwang99
        1
    hansonwang99  
    OP
       2019-02-28 08:23:39 +08:00
    由于能力有限,大家如有问题可以去公众号 CodeSheep 或者博客 www.codesheep.cn 一起交流
    xomix
        2
    xomix  
       2019-02-28 09:02:09 +08:00
    @Livid 这个按定义是宣传贴吧
    peyppicp
        3
    peyppicp  
       2019-02-28 11:35:31 +08:00 via iPhone
    有 git 地址吗?
    elementpps1
        4
    elementpps1  
       2019-02-28 17:48:54 +08:00
    图一是哪款
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2581 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 11:01 · PVG 19:01 · LAX 03:01 · JFK 06:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.