Java操作Elasticsearch

版权声明:本文为博主原创文章,转载请注明链接地址。谢谢! https://blog.csdn.net/wdy_2099/article/details/85337634

一.创建maven工程

工程结构
在这里插入图片描述

pom添加如下依赖:
	<properties>
        <es-version>5.6.1</es-version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>${es-version}</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>transport</artifactId>
            <version>${es-version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.7.3</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.7.3</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>1.9.13</version>
        </dependency>
    </dependencies>
Article.java
public class Article {

    private String atcId;
    private String title;
    private String content;
log4j2.xml
<?xml version="1.0" encoding="utf-8" ?>
<Configuration xmlns="http://logging.apache.org/log4j/2.0/config">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%m%n"></PatternLayout>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="Console"></AppenderRef>
        </Root>
    </Loggers>
</Configuration>

二.测试API

2.1创建索引,删除索引


    @Test
    public void esTest() throws UnknownHostException {
        //获取集群信息
        Settings settings = Settings.builder().put("cluster.name","my-es-search").build();
        //获取客户端
        PreBuiltTransportClient preBuiltTransportClient = new PreBuiltTransportClient(settings);
        //连接指定客户端主机
        preBuiltTransportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.1.117"), 9300));
        System.out.println("" + preBuiltTransportClient.toString());
        //创建索引
		preBuiltTransportClient.admin().indices().prepareCreate("blog").get();
        //删除索引
//        preBuiltTransportClient.admin().indices().prepareDelete("blog").get();
        //最后关闭客户端
        preBuiltTransportClient.close();
    }

2.1插入文档

1)json格式插入文档

@Test
    public void esTest() throws UnknownHostException {
        //获取集群信息
        Settings settings = Settings.builder().put("cluster.name","my-es-search").build();
        //获取客户端
        PreBuiltTransportClient preBuiltTransportClient = new PreBuiltTransportClient(settings);
        //连接指定客户端主机
        preBuiltTransportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.1.117"), 9300));
        //插入JSON文档,没有index会创建
   		Article article = new Article();
        article.setAtcId("1");
        article.setTitle("第一文");
        article.setContent("浏览器查看http://sdafadf:9200/blog2");
        String articleJson = JsonUtils.objectToJson(article);
        //prepareIndex(index名,type名,documentId)
        IndexResponse indexResponse = preBuiltTransportClient.prepareIndex("blog", "article", "1")
                .setSource(articleJson, XContentType.JSON)
                .get();
 	    System.out.println("1" + indexResponse.getId());        //输出 11
        System.out.println("2" + indexResponse.getIndex());     //输出 2blog
        System.out.println("3" + indexResponse.getType());      //输出 3article
        System.out.println("4" + indexResponse.getResult());    //输出 4CREATED
        System.out.println("5" + indexResponse.getShardId());   //输出 5[blog][1]
        System.out.println("6" + indexResponse.getShardInfo()); //输出 6ShardInfo{total=1, successful=1, failures=[]}
        System.out.println("7" + indexResponse.getVersion());   //输出 71
        System.out.println("8" + indexResponse.getLocation(""));//输出 8/blog/article/1?routing=
        //最后关闭客户端
        preBuiltTransportClient.close();
    }

2)以map形式插入文档

@Test
    public void esTest() throws UnknownHostException {
        //获取集群信息
        Settings settings = Settings.builder().put("cluster.name","my-es-search").build();
        //获取客户端
        PreBuiltTransportClient preBuiltTransportClient = new PreBuiltTransportClient(settings);
        //连接指定客户端主机
        preBuiltTransportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.1.117"), 9300));
         //map形式插入文档
        Map<String,Object> map = new HashMap<>();
        map.put("atcId","2");
        map.put("title","第二文");
        map.put("content","ID:ffmkiejjmecolpfloofpjologoblkegm\n");
        IndexResponse indexResponse2 = preBuiltTransportClient.prepareIndex("blog", "article", "2")
                .setSource(map)
                .get();
        //最后关闭客户端
        preBuiltTransportClient.close();
    }

3)以ES构建器方式插入

@Test
    public void esTest() throws UnknownHostException {
        //获取集群信息
        Settings settings = Settings.builder().put("cluster.name","my-es-search").build();
        //获取客户端
        PreBuiltTransportClient preBuiltTransportClient = new PreBuiltTransportClient(settings);
        //连接指定客户端主机
        preBuiltTransportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.1.117"), 9300));
         //ES构建器形式插入文档
        XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject()
                .field("atcId", "3")
                .field("title", "第3文")
                .field("content", "页面空白 报错信息 此时页面一片空白 报错原因 Babel 默认只转换")
                .endObject();
        IndexResponse indexResponse3 = preBuiltTransportClient.prepareIndex("blog", "article", "3")
                .setSource(xContentBuilder)
                .get();
        //最后关闭客户端
        preBuiltTransportClient.close();
    }

插入后效果:
在这里插入图片描述

2.2搜索文档

1)获取单条数据prepareGet(index名,type名,es唯一id)

    @Test
    public void esTest() throws IOException {
        //获取集群信息
        Settings settings = Settings.builder().put("cluster.name", "my-es-search").build();
        //获取客户端
        PreBuiltTransportClient preBuiltTransportClient = new PreBuiltTransportClient(settings);
        //连接指定客户端主机
        preBuiltTransportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.1.117"), 9300)); 
        //获取数据
        GetResponse getResponse = preBuiltTransportClient.prepareGet("blog", "article", "1").get();
        System.out.println("获取的数据为:" + getResponse.getSourceAsString());//获取的数据为:{"atcId":"1","title":"第一文","content":"浏览器查看http://hadoop102:9200/blog2"}
        //最后关闭客户端
        preBuiltTransportClient.close();
    }

2)获取多条数据

具体请看注释:

    @Test
    public void esTest() throws IOException {
        //获取集群信息
        Settings settings = Settings.builder().put("cluster.name", "my-es-search").build();
        //获取客户端
        PreBuiltTransportClient preBuiltTransportClient = new PreBuiltTransportClient(settings);
        //连接指定客户端主机
        preBuiltTransportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.1.117"), 9300));
        //连续多个add一起写,适用于获取不同index,不同type的数据
        MultiGetResponse multiGetItemResponses = preBuiltTransportClient.prepareMultiGet().add("blog", "article", "1").add("blog", "article", "2").get();
        for (MultiGetItemResponse itemResponses : multiGetItemResponses) {
            GetResponse getResponse = itemResponses.getResponse();
            //如果真的存在,则打印
            if (getResponse.isExists()) {
                System.out.println("获取的数据为:" + getResponse.getSourceAsString());//
            }
        }
        System.out.println("#########br###########");
        //add()中要的id是一个不定长参数,可以一次性获取多个id的document
        //适用于获取同一index,同一type的数据
        MultiGetResponse multiGetItemResponses1 = preBuiltTransportClient.prepareMultiGet().add("blog", "article", "1", "2").get();
        for (MultiGetItemResponse itemResponses : multiGetItemResponses1) {
            GetResponse getResponse = itemResponses.getResponse();
            //如果真的存在,则打印
            if (getResponse.isExists()) {
                System.out.println("获取的数据为:" + getResponse.getSourceAsString());//
            }
        }
        //最后关闭客户端
        preBuiltTransportClient.close();
    }
    最终输出为:
    获取的数据为:{"atcId":"1","title":"第一文","content":"浏览器查看http://hadoop102:9200/blog2"}
	获取的数据为:{"atcId":"2","title":"第二文","content":"ID:ffmkiejjmecolpfloofpjologoblkegm\n"}
	#########br###########
	获取的数据为:{"atcId":"1","title":"第一文","content":"浏览器查看http://hadoop102:9200/blog2"}
	获取的数据为:{"atcId":"2","title":"第二文","content":"ID:ffmkiejjmecolpfloofpjologoblkegm\n"}

2.3更新文档

更新文档的方式和插入文档的神似,都是那几种方式,如:
1)prepareUpdate的方式

@Test
    public void esTest() throws IOException {
        //获取集群信息
        Settings settings = Settings.builder().put("cluster.name", "my-es-search").build();
        //获取客户端
        PreBuiltTransportClient preBuiltTransportClient = new PreBuiltTransportClient(settings);
        //连接指定客户端主机
        preBuiltTransportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.1.117"), 9300));
           //更新文档
        Map<String, Object> map = new HashMap<>();
        map.put("title", "第一文-update文档");
        UpdateResponse updateResponse = preBuiltTransportClient.prepareUpdate("blog", "article", "1").setDoc(map).get();
        System.out.println("" + updateResponse);//UpdateResponse[index=blog,type=article,id=1,version=2,result=updated,shards=ShardInfo{total=2, successful=1, failures=[]}]
        //最后关闭客户端
        preBuiltTransportClient.close();
    }

修改后的效果:
在这里插入图片描述
2)UpdateRequest的方式

		//##############此处获取preBuiltTransportClient和上面代码中的一样哈,就不重复了,直接关键代码##########
 		Map<String, Object> map = new HashMap<>();
        map.put("title", "第一文-第二次update文档");
        //UpdateRequest(String index, String type, String id)
        preBuiltTransportClient.update(new UpdateRequest("blog", "article", "1")
                .doc(map) //此处doc里可以放json字符串, map,XContentBuilder.jsonBuilder IndexRequest等
        ).actionGet();
        //##########关闭clien代码###########

修改后的效果:
在这里插入图片描述

2.4 upsert文档(更新插入)

这种方式是:存在修改,不存在则插入

		//##############此处获取preBuiltTransportClient和上面代码中的一样哈,就不重复了,直接关键代码##########
 		Map<String, Object> map = new HashMap<>();
        map.put("atcId", "8");
        map.put("title", "update的文档");
        map.put("content", "This is update的文档content");
        Map<String, Object> mapUpsert = new HashMap<>();
        mapUpsert.put("atcId", "8");
        mapUpsert.put("title", "upsert的文档");
        mapUpsert.put("content", "This is upsert的文档content");
        preBuiltTransportClient.update(new UpdateRequest("blog", "article", "8")
                //此处doc和upsert里可以放json字符串, map,XContentBuilder.jsonBuilder IndexRequest等
                //如果不存在插入mapUpsert的数据,否则修改成map的数据,执行2次可看效果
                .doc(map).upsert(mapUpsert)
        ).actionGet();
        //##########关闭clien代码###########

第一次执行后的效果:(因为id=8不存在,所以插入mapUpsert的数据)
在这里插入图片描述
第二次执行后的效果:(因为id=8已存在,所以修改为map的数据)
在这里插入图片描述

2.5 删除文档

删除就是根据id删除对应文档
比如:这里删除id=2的文档

		//##############此处获取preBuiltTransportClient和上面代码中的一样哈,就不重复了,直接关键代码##########
        DeleteResponse deleteResponse = preBuiltTransportClient.prepareDelete("blog", "article", "2").get();
        //DeleteRequest的方式,差不多的操作方式
//        DeleteResponse deleteResponse1 = preBuiltTransportClient.delete(new DeleteRequest("blog", "article", "2")).actionGet();        
        System.out.println("删除结果:" + deleteResponse);
        //删除结果:DeleteResponse[index=blog,type=article,id=2,version=2,result=deleted,shards=ShardInfo{total=2, successful=1, failures=[]}]
        //##########关闭clien代码###########

删除后,发现id=2的数据没有了:
在这里插入图片描述

三.高级查询

3.1 QueryBuilders.matchAllQuery() 查询所有

		//##############此处获取preBuiltTransportClient和上面代码中的一样哈,就不重复了,直接关键代码##########
        SearchResponse searchResponse = preBuiltTransportClient.prepareSearch("blog").setTypes("article")
                .setQuery(QueryBuilders.matchAllQuery()).get();
        SearchHits searchHits = searchResponse.getHits();
        System.out.println("查询的总条数:" + searchHits.getTotalHits());//查询的总条数:3
        for (SearchHit searchHit : searchHits) {
            System.out.println("" + searchHit.getSourceAsString());
        }
        //{"atcId":"8","title":"update的文档","content":"This is update的文档content"}
        //{"atcId":"1","title":"第一文-第二次update文档","content":"浏览器查看http://hadoop102:9200/blog2"}
        //{"atcId":"3","title":"第3文","content":"页面空白 报错信息 此时页面一片空白 报错原因 Babel 默认只转换"}
        //##########关闭clien代码###########

3.2 QueryBuilders.queryStringQuery(keyword) 根据所有字段分词查询

现在的数据里只有id=1和id=8两条数据里有update关键字,且在不同的字段中,根据所有字段分词查询:在这里是指既扫描title,又扫描content字段。所以这2个字段中包含update关键字的都会被查询出来。

		//##############此处获取preBuiltTransportClient和上面代码中的一样哈,就不重复了,直接关键代码##########
        String keyword = "update";
        SearchResponse searchResponse = preBuiltTransportClient.prepareSearch("blog").setTypes("article")
                .setQuery(QueryBuilders.queryStringQuery(keyword)).get();
        SearchHits searchHits = searchResponse.getHits();
        System.out.println("查询的总条数:" + searchHits.getTotalHits());//查询的总条数:3
        for (SearchHit searchHit : searchHits) {
            System.out.println("" + searchHit.getSourceAsString());
        }
        //查询的总条数:2
        //{"atcId":"8","title":"update的文档","content":"This is update的文档content"}
        //{"atcId":"1","title":"第一文-第二次update文档","content":"浏览器查看http://hadoop102:9200/blog2"}
        //##########关闭clien代码###########

3.3 QueryBuilders.wildcardQuery(字段, 通配符关键字) 通配符查询

   ------->可用的通配符有:
   * :表示0个或多个字符
   ? :表示单个字符

1)星号通配符

		//##############此处获取preBuiltTransportClient和上面代码中的一样哈,就不重复了,直接关键代码##########
        String keywordLike = "*第*";
        SearchResponse searchResponse = preBuiltTransportClient.prepareSearch("blog").setTypes("article")
                .setQuery(QueryBuilders.wildcardQuery("title",keywordLike)).get();
        SearchHits searchHits = searchResponse.getHits();
        System.out.println("查询的总条数:" + searchHits.getTotalHits());//查询的总条数:3
        for (SearchHit searchHit : searchHits) {
            System.out.println("" + searchHit.getSourceAsString());
        }
        //查询的总条数:2
		//"atcId":"1","title":"第一文-第二次update文档","content":"浏览器查看http://hadoop102:9200/blog2"}
		//"atcId":"3","title":"第3文","content":"页面空白 报错信息 此时页面一片空白 报错原因 Babel 默认只转换"}

        //##########关闭clien代码###########

2)问号通配符

		//##############此处获取preBuiltTransportClient和上面代码中的一样哈,就不重复了,直接关键代码##########
        String keywordLike = "第?";//?第
        SearchResponse searchResponse = preBuiltTransportClient.prepareSearch("blog").setTypes("article")
                .setQuery(QueryBuilders.wildcardQuery("title",keywordLike)).get();
        SearchHits searchHits = searchResponse.getHits();
        System.out.println("查询的总条数:" + searchHits.getTotalHits());//查询的总条数:3
        for (SearchHit searchHit : searchHits) {
            System.out.println("" + searchHit.getSourceAsString());
        }
        //查询的总条数:0
        //这个是因为默认的分词器对中文的分词效果很差,所以查询不到数据,后面会介绍ik分词器
        //##########关闭clien代码###########

3.4 QueryBuilders.termQuery(字段, 词条关键字) 词条查询

		//##############此处获取preBuiltTransportClient和上面代码中的一样哈,就不重复了,直接关键代码##########
        String term = "第";
        SearchResponse searchResponse = preBuiltTransportClient.prepareSearch("blog").setTypes("article")
                .setQuery(QueryBuilders.termQuery("title",term)).get();
        SearchHits searchHits = searchResponse.getHits();
        System.out.println("查询的总条数:" + searchHits.getTotalHits());//查询的总条数:3
        for (SearchHit searchHit : searchHits) {
            System.out.println("" + searchHit.getSourceAsString());
        }
        //查询的总条数:2
		//"atcId":"1","title":"第一文-第二次update文档","content":"浏览器查看http://hadoop102:9200/blog2"}
		//"atcId":"3","title":"第3文","content":"页面空白 报错信息 此时页面一片空白 报错原因 Babel 默认只转换"}

        //##########关闭clien代码###########

3.5 QueryBuilders.fuzzyQuery(字段, 关键字) 模糊查询

这个区别于mysql的模糊查询,mysql的模糊查询和星号*通配符的方式类似的,es的模糊查询是根据模糊程度查询对应数据:
使用编辑距离的模糊查询,计算量较大,但是对用户拼写错的场景比较有用(如:模糊查询4)
可以通过设置属性来限定查询的模糊程度:
1)指定最小相似度偏差: “min_similarity”:1
2) 模糊查询将扩展到的默认最大数。默认值为50:maxExpansions。

		//##############此处获取preBuiltTransportClient和上面代码中的一样哈,就不重复了,直接关键代码##########
        //模糊查询1:Babel
        String fuzzy = "Babel";
        SearchResponse searchResponse = preBuiltTransportClient.prepareSearch("blog").setTypes("article")
                .setQuery(QueryBuilders.fuzzyQuery("content",fuzzy)).get();
        SearchHits searchHits = searchResponse.getHits();
        System.out.println("查询的总条数:" + searchHits.getTotalHits());//查询的总条数:3
        for (SearchHit searchHit : searchHits) {
            System.out.println("" + searchHit.getSourceAsString());
        }
        //查询的总条数:1
		//"atcId":"3","title":"第3文","content":"页面空白 报错信息 此时页面一片空白 报错原因 Babel 默认只转换"}
		
		//模糊查询2:babel(大小写的转换,全大写BABEL是查询不到的)
        String fuzzy = "nabel";
        SearchResponse searchResponse = preBuiltTransportClient.prepareSearch("blog").setTypes("article")
                .setQuery(QueryBuilders.fuzzyQuery("content",fuzzy)).get();
        SearchHits searchHits = searchResponse.getHits();
        System.out.println("查询的总条数:" + searchHits.getTotalHits());//查询的总条数:3
        for (SearchHit searchHit : searchHits) {
            System.out.println("" + searchHit.getSourceAsString());
        }
        //查询的总条数:1
		//"atcId":"3","title":"第3文","content":"页面空白 报错信息 此时页面一片空白 报错原因 Babel 默认只转换"}
		
		//模糊查询3:updat(去掉两边的其中1个字符)
        String fuzzy = "updat";
        SearchResponse searchResponse = preBuiltTransportClient.prepareSearch("blog").setTypes("article")
                .setQuery(QueryBuilders.fuzzyQuery("content",fuzzy)).get();
        SearchHits searchHits = searchResponse.getHits();
        System.out.println("查询的总条数:" + searchHits.getTotalHits());//查询的总条数:3
        for (SearchHit searchHit : searchHits) {
            System.out.println("" + searchHit.getSourceAsString());
        }
        //查询的总条数:1
		//{"atcId":"8","title":"update的文档","content":"This is update的文档content"}

		//模糊查询4:upfate(写错一个字符)
        String fuzzy = "upfate";
        SearchResponse searchResponse = preBuiltTransportClient.prepareSearch("blog").setTypes("article")
                .setQuery(QueryBuilders.fuzzyQuery("content",fuzzy)).get();
        SearchHits searchHits = searchResponse.getHits();
        System.out.println("查询的总条数:" + searchHits.getTotalHits());//查询的总条数:3
        for (SearchHit searchHit : searchHits) {
            System.out.println("" + searchHit.getSourceAsString());
        }
        //查询的总条数:1
		//{"atcId":"8","title":"update的文档","content":"This is update的文档content"}

		//模糊查询5:date(去掉2个字符)
        String fuzzy = "upfate";
        SearchResponse searchResponse = preBuiltTransportClient.prepareSearch("blog").setTypes("article")
                .setQuery(QueryBuilders.fuzzyQuery("content",fuzzy)).get();
        SearchHits searchHits = searchResponse.getHits();
        System.out.println("查询的总条数:" + searchHits.getTotalHits());//查询的总条数:3
        for (SearchHit searchHit : searchHits) {
            System.out.println("" + searchHit.getSourceAsString());
        }
        //查询的总条数:0
        //##########关闭clien代码###########

3.6 组合查询

//---->: queryStringQuery会将关键字进行分词,然后再对应列上进行查询匹配,不指定对应列的,在所有列进行查询
//---->: boolQuery:组合查询,多条件一起查询
//---->: must:必须条件 类似and
//---->: mustNot: 必须不条件
//---->: should: 可能含有,类似 or
//---->: filter:过滤,一般配合rangeQuery().from().to()使用

 String[] isShowArr = {0,1};
 BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
 //这里是查询:显示状态是0,1,且商品名称包含“苹果”的商品。
 boolQuery.must(QueryBuilders.termsQuery("isShow", isShowList)) //termsQuery传集合,termQuery传单个
          .must(QueryBuilders.queryStringQuery("苹果").field("productName"));

3.7 其他查询

//范围查询,类似mysql的between and:查询生日在("1990-01-01")到("1999-12-31")的
QueryBuilder qb = QueryBuilders.rangeQuery("birthday").from("1990-01-01").to("1999-12-31");
//前缀查询:查询姓名字段以“张”开头的
QueryBuilder qb = QueryBuilders.prefixQuery("name","张")//ids查询:查询指定ids的对应文档
QueryBuilder qb = QueryBuilders.idsQuery().addIds("1","3");
//type查询,查询指定index下指定type的所有文档
QueryBuilder qb = QueryBuilders.typeQuery("blog");

四.mapping

数据如何存放到索引对象上,需要有一个映射配置,包括:数据类型、是否存储、是否分词等
mapping是类似于数据库中的表结构定义,主要作用如下:
定义index下的字段名
定义字段类型,比如数值型、浮点型、布尔型等
定义倒排索引相关的设置,比如是否索引、记录position等
1)在插入文档的时候,es会根据插入的数据自动生成mapping映射
在这里插入图片描述
2)自定义mapping
首先,创建一个空的index(blog2)

        preBuiltTransportClient.admin().indices().prepareCreate("blog2").get();

此时mapping是空的{}
在这里插入图片描述
然后,新增mapping

// 1设置mapping
        XContentBuilder builder = XContentFactory.jsonBuilder()
                .startObject()
                .startObject("article")
                .startObject("properties")
                .startObject("id")
                .field("type", "string")
                .field("store", "yes")
                .endObject()
                .startObject("title")
                .field("type", "string")
                .field("store", "no")
                .endObject()
                .startObject("content")
                .field("type", "string")
                .field("store", "yes")
                .endObject()
                .endObject()
                .endObject()
                .endObject();

        // 2 添加mapping
        PutMappingRequest mapping = Requests.putMappingRequest("blog2").type("article").source(builder);
        preBuiltTransportClient.admin().indices().putMapping(mapping).get();

刷新,重新查看索引信息如下:
在这里插入图片描述
发现:string会被自动转换成text类型

【end】这个就是Java操作Elasticsearch的常用API啦,关于ik分词器,下篇再见。

猜你喜欢

转载自blog.csdn.net/wdy_2099/article/details/85337634