ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java es 入门高亮,分页,模糊,查询。

2021-09-19 11:34:57  阅读:244  来源: 互联网

标签:高亮 java tags 查询 Tag new import es


es模糊查询


前言

es是一个优秀的搜索框架,最近项目上有用到,但是csdn能找到的资料有限,因此出个文章仅供参考,不对的地方大家可以指出,共同进步。 本文针对初学es使用es新建索引到查询教程,本文基于es版本为:elasticsearch-7.14.1-linux-x86_64.tar.gz, kibana版本为:kibana-7.14.1-linux-x86_64.tar.gz 安装过程就不介绍了,同学们可以自行百度安装。

提示:以下是本篇文章正文内容,下面案例可供参考

一、es 索引建立以及kibana的相关操作

1.1 kibana操作

我们常见的搜索类型有
1.time 可以有很多格式的时间类型,我这里使用了最常用的格式, 2.keyword,使用在已经确定的枚举类型的,例如男、女
3.text,使用在模糊查找的字段,例如文章内容等
4.list,使用在1对多的关系中,例如一个人的标签,可爱、善良
这里我都新建了这几种类型,可以参考如何使用。

1.1.1 新建索引

新建索引名称为test,属性有name,nameType,time 和一个tag标签list

PUT /test
{
  "mappings": {
    "properties": {
        "name":    { "type": "text"  },
        "nameType":     { "type": "text"  },
        "time": {
          "type": "date",
          "format": "yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || yyyy/MM/dd HH:mm:ss|| yyyy/MM/dd ||epoch_millis"
        },
      "tags": {
        "properties": {
          "id": {"type":"keyword"},
                  "tagName": {
                    "type": "text"
                  }
        }
      }
      }
    }

}

1.1.2 在kibana上新建索引,看到以下提示就是新建成功

在这里插入图片描述

1.1.3 删除索引

DELETE /test

在这里插入图片描述

1.1.4 查询所有数据

GET /test/_search
{
  "query": {"match_all": {
    
  }}
}

1.1.5 查看索引的映射情况

GET /test

二、使用步骤

1.本文基于springboot,要先引入maven依赖

代码如下(示例):

    <properties>
        <java.version>1.8</java.version>
        <elasticsearch.version>7.14.1</elasticsearch.version>
    </properties>
 <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.20</version>
        </dependency> 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.9</version>
        </dependency>
        <dependency>
            <groupId>apache-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.7.0</version>
        </dependency>

主要是spring-boot-starter-data-elasticsearch,其他有用到就一起粘贴下来了。使用的springboot版本为

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

2.建立连接

建立如下的配置,在control层就可以直接注入使用连接
一般es的端口为9200,如果有账号密码的也可以使用账号密码连接
这里就不展示了,可以看看api就知道了。

代码如下(示例):

package com.example.springdemo.demo.conifg;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class EsConfig {

        @Bean("restHighLevelClient")
        public RestHighLevelClient esRestClient(){
            RestHighLevelClient client = new RestHighLevelClient(
                    RestClient.builder(
                            //在这里配置你的elasticsearch的地址
                            new HttpHost("123.xx.xx.xxx", 9200, "http")
                    )
            );
            return client;
        }

}

3 es插入数据

3.1注入client

    @Autowired
    private RestHighLevelClient restHighLevelClient;

3.2 插入数据

这里只介绍了单个插入,批量插入使用client.bulk方法即可

    private String insertData(EsModel esModel) throws IOException {
    //要插入的索引名称test
        IndexRequest request = new IndexRequest("test");
        request.id(UUID.randomUUID().toString());
        request.timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");
        //将我们的数据放入请求,json
        request.source(JSON.toJSONString(esModel),XContentType.JSON);
        //request.source(describe);
        System.out.println("json:"+JSON.toJSONString(esModel));
        //客服端发送请求
        IndexResponse index = restHighLevelClient.index(request, RequestOptions.DEFAULT);
        request.source(JSON.toJSONString(esModel),XContentType.JSON);
        String result = index.toString()+"/n"+index.toString();
        System.out.println(result);
        return result;
    }

这里的插入格式es支持两种格式,一种是json格式的,如上面的写法,一种是map格式的,

JSON.parseObject(JSON.toJSONString(user), Map.class);

map格式的可以使用json的工具类直接转换即可。

3.2.1 插入数据control层如下

    @RequestMapping("/testInsert")
    String testInsert() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        StringBuilder sb = new StringBuilder();
        EsModel user = new EsModel();
        user.setName("王小明");
        user.setNameType("男");
        user.setTime(new Date());
        List<Tag> tags = new ArrayList<>();
        Tag tag = new Tag();
        tag.setId(UUID.randomUUID().toString());
        tag.setTagName("活泼");
        Tag tag1 = new Tag();
        tag1.setId(UUID.randomUUID().toString());
        tag1.setTagName("开朗");
        Tag tag11= new Tag();
        tag11.setId(UUID.randomUUID().toString());
        tag11.setTagName("活泼2");
        tags.add(tag);
        tags.add(tag1);
        tags.add(tag11);
        user.setTags(tags);
        String s1 = insertData(user);
        sb.append(s1).append("/n");

        EsModel user2 = new EsModel();
        user2.setName("王小二");
        user2.setNameType("男");
        user2.setTime(new Date());
        List<Tag> tags4 = new ArrayList<>();
        Tag tag4 = new Tag();
        tag4.setId(UUID.randomUUID().toString());
        tag4.setTagName("高富活泼");
        Tag tag5 = new Tag();
        tag5.setId(UUID.randomUUID().toString());
        tag5.setTagName("英俊");
        tags4.add(tag4);
        tags4.add(tag5);
        user2.setTags(tags4);
        String s3 = insertData(user2);
        sb.append(s3).append("/n");


        EsModel user1 = new EsModel();
        user1.setName("王小红");
        user1.setNameType("女");
        user1.setTime(new Date());
        List<Tag> tags1 = new ArrayList<>();
        Tag tag2 = new Tag();
        tag2.setId(UUID.randomUUID().toString());
        tag2.setTagName("漂亮");
        Tag tag3 = new Tag();
        tag3.setId(UUID.randomUUID().toString());
        tag3.setTagName("可爱");
        tags1.add(tag3);
        tags1.add(tag2);
        user1.setTags(tags1);
        String s = insertData(user1);
        sb.append(s).append("/n");
        return  sb.toString();

    }

3.2.2 注意点

这里需要注意的是,如果格式是时间格式,我们需要在实体上加个jsonfield注解否则转换成string的时候会报错。实体类如下

package com.example.springdemo.demo.model;

import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.io.Serializable;
import java.text.Format;
import java.util.Date;
import java.util.List;

@Data
public class EsModel implements Serializable {

    private String name;
    private String nameType;

//    @Field(type = FieldType.Date, format= DateFormat.custom,pattern ="yyyy-MM-dd HH:mm:ss")
//    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern ="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
    @JSONField(format="yyyy-MM-dd HH:mm:ss")
    private Date time;

    private List<Tag> tags;

}

package com.example.springdemo.demo.model;

import lombok.Data;

@Data
public class Tag {
    private String id;
    private String tagName;
}

执行插入指令显示如下
http://localhost:8008/search/testInsert
在这里插入图片描述
去kibana查询下数据是否插入
执行上面的查询所有数据指令可以看到数据已经成功插入
在这里插入图片描述

3.查询

接下来我们可以进行查询了,这里我们主要用的是中文查询,中文搜索的时候,和查询的时候都可以指定分词器,分词器的作用其实就是可以智能的把语句分成不同的词语索引,例如我爱中国,可以分解成,我,爱,中国,如果不加分词器,则会分解成我,爱,中,国,和更多的组合,一般会使用分词器,我这里就不使用了。
这样在搜索的时候就可以更精确的查找到用户想要的结果。
我们可以在kibana测试一下

GET _analyze
{"text":"我爱中国"} 

在这里插入图片描述
使用分词器分词

GET _analyze
{"analyzer":"ik_max_word",
  "text":"我爱中国"} 

在这里插入图片描述

3.1 查询代码如下

实际项目使用的时候往往不会像一般简单教程里面的这么简单,分页,模糊查询,高亮,排序,是基本的要求,所以我就构造了下面的查询
这里的查询条件构造如下:
查询一个boolquery,也就是一个是否的条件查询
这里查询为:并且(must) nametype 含有男
并且(代码里面用must表示)
(
或者(代码用shuld) tags.tagName 中含有 活字
)
list里面的字段用list名字.属性表示。

@RequestMapping("/testSearch")
    String contextLoads() throws IOException {
        //1、创建查询请求,规定查询的索引
        SearchRequest request = new SearchRequest("test");
        //2、创建条件构造
        SearchSourceBuilder builder = new SearchSourceBuilder();
        //3、构造条件
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("nameType","男"));
        BoolQueryBuilder condition = new BoolQueryBuilder();

        condition.should(QueryBuilders.matchPhraseQuery("tags.tagName","活"));

        boolQueryBuilder.must(condition);

        builder.query(boolQueryBuilder);

        //高亮查询
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        HighlightBuilder.Field field = new HighlightBuilder.Field("tags.tagName");
        highlightBuilder.field(field);
        highlightBuilder.requireFieldMatch(false);
//        highlightBuilder.preTags("<em>");
//        highlightBuilder.postTags("</em>");
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");

        builder.highlighter(highlightBuilder);



        //指定返回的字段
        String[] fetch ={"name","nameType","tags.tagName"};
        builder.fetchSource(fetch,null);

        builder.from(0);
        builder.size(10);

        //根据匹配度排序
        builder.sort("_score",SortOrder.DESC);
        //根据时间排序,asc升序
        builder.sort("time", SortOrder.DESC);

        //4、将构造好的条件放入请求中
        request.source(builder);

        //5、开始执行发送request请求
        SearchResponse searchResponse = restHighLevelClient.search(request, RequestOptions.DEFAULT);

        //6、开始处理返回的数据
        SearchHit[] hits = searchResponse.getHits().getHits();
        StringBuilder sb = new StringBuilder();
        for (SearchHit hit : hits) {
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            System.out.println("highlight"+highlightFields);
            HighlightField content = highlightFields.get("tags.tagName");
            //原始数据
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            System.out.println("sourcemap"+sourceAsMap);
            //高亮的字段替换
            if (content!=null){
                Text[] fragments = content.fragments();
                sourceAsMap.put("tags",Arrays.asList(fragments));
            }
            sb.append(sourceAsMap);
        }
        System.out.println("sb"+ sb.toString());
        return sb.toString();
    }

这里的高亮显示,但是页面上不显示出来,这里换成了页面可以显示出来的格式
查询的结果如图所示
在这里插入图片描述

总结

例如:以上就是今天要讲的内容,本文仅仅简单介绍了es的基本使用,更多的查询例如termsquery精确查找,和fuzzyquery近似查找,例如国中,可以帮你搜索出中国,还有范围查询等等高级使用,可以查询es官方文档,这里仅作为一个入门介绍,如果该文章对你有用,可以点赞一下呀,比较写文章不容易,还是要花些时间的。

标签:高亮,java,tags,查询,Tag,new,import,es
来源: https://blog.csdn.net/qq_34526237/article/details/120377311

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有