• ElasticSearch详解


    一、引言

    1.1 海量数据

    在海量数据中执行搜索功能时,如果使用MySQL,效率太低。

    1.2 全文检索

    在海量数据中执行搜索功能时,如果使用MySQL,效率太低。

    1.3 高亮显示

    将搜索关键字,以红色的字体展示。

    二、ES概述

    2.1 ES的介绍

    • ES是一个使用Java语言并且基于Lucene编写的搜索引擎框架,他提供了分布式的全文搜索功能,提供了一个统一的基于RESTful风格的WEB接口,官方客户端也对多种语言都提供了相应的API。

    • LuceneLucene本身就是一个搜索引擎的底层。

    • 分布式:ES主要是为了突出他的横向扩展能力。

    • 全文检索将一段词语进行分词,并且将分出的单个词语统一的放到一个分词库中,在搜索时,根据关键字去分词库中检索,找到匹配的内容。(倒排索引)

    • RESTful风格的WEB接口:操作ES很简单,只需要发送一个HTTP请求,并且根据请求方式的不同,携带参数的同,执行相应的功能。

    • 应用广泛:Github.com,WIKI,Gold Man用ES每天维护将近10TB的数据。

    2.2 ES的由来

    ES回忆时光

    2.3 ES和Solr

    • Solr在查询死数据时,速度相对ES更快一些。但是数据如果是实时改变的,Solr的查询速度会降低很多,ES的查询的效率基本没有变化

    • Solr搭建基于需要依赖Zookeeper来帮助管理。ES本身就支持集群的搭建,不需要第三方的介入。

    • 最开始Solr的社区可以说是非常火爆,针对国内的文档并不是很多。在ES出现之后,ES的社区火爆程度直线上升,ES的文档非常健全。

    • ES对现在云计算和大数据支持的特别好。

    2.4 倒排索引

    将存放的数据,以一定的方式进行分词,并且将分词的内容存放到一个单独的分词库中。

    当用户去查询数据时,会将用户的查询关键字进行分词。

    然后去分词库中匹配内容,最终得到数据的id标识。

    根据id标识去存放数据的位置拉取到指定的数据。

    检索的时候 先将检索的内容分词,然后去分词库匹配 拿到匹配数据的索引 再根据索引去数据存储的位置 拿到匹配的数据

    elk elasticsearch (存储分析检索数据) + logstash (采集数据) + kibana (展示数据的图形化界面)

    倒排索引

    2.5基本概念

    2.5.1 Index (索引)

    • 动词 ,相当于Mysql 中的insert
    • 名词, 相当于Mysql 中的 Database

    2.5.2 Type (类型)

    在Index(索引)中 ,可以定义一个或多个类型。

    类似Mysql 中的table ,每一种类型的数据放在一起

    2.5.3 Document (文档)

    保存在某个索引(index)下,某种类型(type)的一个数据(Document) ,文档是json 格式的,Document 就像是Mysql 中某个table里面的内容。

    三、 ElasticSearch安装

    3.1 安装ES&Kibana 不建议

    1).下载镜像文件

    1. docker pull elasticsearch:7.4.2
    2. docker pull kibana:7.4.2

     2).创建挂载目录

    1. mkdir -p /mydata/elasticsearch/config
    2. mkdir -p /mydata/elasticsearch/data
    3. echo "http.host: 0.0.0.0" >> /mydata/elasticsearch/config/elasticsearch.yml

     3).启动容器

    1. docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
    2. -e "discovery.type=single-node" \
    3. -e ES_JAVA_OPTS="-Xms512m -Xmx1024m" \
    4. -v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
    5. -v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
    6. -v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
    7. -d elasticsearch:7.4.2
    8. #如果 启动elasticsearch 失败, 查看 日期 docker logs 容器id   查看 某容器的日志
    9. #docker logs 容器id
    10. # 需要 给 elasticsearch 目录授权
    11. #chmod -R 777 /mydata/elasticsearch/     给整个目录授权   可读可写可执行
    12. #在启动容器 应该就好了

     4).启动kibana

    1. docker run --name kibana -e ELASTICSEARCH_URL=http://192.168.5.202:9200 -p 5601:5601\
    2. -d kibana:7.4.2

            测试访问

    • http://192.168.5.202:9200     如访问不到 查看日志
    • http://192.168.5.202:5601     如访问不到 查看日志 看容器内 kibana.yml 中 ip 地址是否正确

    3.1.1 使用docker-compose的方式安装(推荐)

    • mkdir -p /mydata/elasticsearch/config
    • mkdir -p /mydata/elasticsearch/data

    echo "http.host: 0.0.0.0" >> /mydata/elasticsearch/config/elasticsearch.yml

    1. version: "3.1"
    2. services:
    3. elasticsearch:
    4. image: daocloud.io/library/elasticsearch:7.4.2
    5. restart: always
    6. container_name: elasticsearch
    7. environment:
    8.     - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    9. volumes:
    10.     - /opt/docker_elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
    11.     - /opt/docker_elasticsearch/data:/usr/share/elasticsearch/data
    12.     - /opt/docker_elasticsearch/plugins:/usr/share/elasticsearch/plugins
    13. ports:
    14.     - 9200:9200
    15.     - 9300:9300
    16. kibana:
    17.   image: daocloud.io/library/kibana:7.4.2
    18.   restart: always
    19.   container_name: kibana
    20.   ports:
    21.     - 5601:5601
    22.   environment:
    23.     - elasticsearch_url=http://192.168.40.102:9200
    24.   depends_on:
    25.     - elasticsearch

    9300 端口 为 es 集群间组件的通信端口,9200 端口为浏览器访问的http 协议resetful 端口

    记得 给文件夹授权 授权之后 再docker-compose up

    1. chmod 777 config
    2. chmod 777 data

    如果访问 http://192.168.40.102:9200 失败,查看日志是否vm内存配置过小elasticsearch启动时遇到的错误。

    问题翻译过来就是:elasticsearch用户拥有的内存权限太小,至少需要262144;

    解决办法1:在 /etc/sysctl.conf文件最后添加一行

    vm.max_map_count=262144 把宿主机内存配大一些

    解决办法2:启动时 指定内存 咱们的安装方法 就是启动时 指定内存

    3.2 安装IK分词器

    ik 分词器 就是 elasticsearch 的一个插件

    注意:

    如果在线安装太慢的话,可以先下载下来压缩包然后手动安装

    把下载的压缩包解压到挂载目录 plugins 下的 ik 文件夹里,

    cd /mydata/elasticsearch/plugins

    mkdir ik

    cd ik 先把压缩包放在 ik 目录中

    unzip elasticsearch-analysis-ik-7.4.2.zip

    解压完之后 可以把压缩包删掉:rm -rf *.zip

    进入容器内部 bin 目录下 执行elasticsearch-plugin list 查看插件列表有没有 ik

    ik_max_wordik 分词器的 一种分词方式还有别的分词方式。

    校验IK分词器

    四、 ElasticSearch基本操作

    4.1 ES的结构 --- 操作es 之前 先了解es 的结构

    4.1.1 索引Index,分片和备份

    • ES的服务中,可以创建多个索引。

    • 每一个索引默认被分成5片存储。

    • 每一个分片都会存在至少一个备份分片。

    • 备份分片默认不会帮助检索数据,当ES检索压力特别大的时候,备份分片才会帮助检索数据。

    • 备份的分片必须放在不同的服务器中。

    理解:

    索引index是es中最大的数据存储单位 ,和mysql 的区别是 一个索引(index)中可以存海量(几亿条)数据 ,如果我们要在几亿条数据中检索出几条想要的数据 效率会很低 所以 es 提供了 一种对索引进行分片的机制 ,ES 天然支持集群,在集群服务器中 ES 把一个索引进行分片 放在不同的服务器上 如下图 例如 有一亿条数据 分成两个分片 每个分片上有5000万条数据 这样做的好处 一是 提高查询速度 二是 提高数据的存储量,另外 为了保证数据的安全 每个主分片会有备份分片 主分片和备份分片在不同的服务器上 , 比如 主分片2 挂掉了 在 ES服务1 上面 还有 主分片2的备份分片 ,这样在一定程度上保证了数据的安全性 避免数据的丢失。但是,如果当前集群中只有一台es服务器,那么,这台服务器上 放的都是主分片,没有备份分片,什么时候扩展了集群中的另一台服务器才会存放备份分片。

    索引分片备份

    4.1.2 类型 Type

    一个索引下,可以创建多个类型。

    Ps:根据版本不同,类型的创建也不同。

    es7 版本 不推荐使用type ,但是还是能用,到后面的es 版本 就不能再使用type 了

    类型

    4.1.3 文档 Doc

    一个类型下,可以有多个文档。这个文档就类似于MySQL表中的多行数据。

    文档

    4.1.4 属性 Field

    一个文档中,可以包含多个属性。类似于MySQL表中的一行数据存在多个列。

    属性

    4.2 操作ES的RESTful语法

    GET请求:

    • http://ip:port/_cat/nodes:查看所有节点 在kibana 中使用 GET _cat/nodes

    • http://ip:port/_cat/health:查看es 健康状况

    • http://ip:port/_cat/master:查看主节点

    • http://ip:port/_cat/indices:查看所有索引 相当于 show databases;

    • http://ip:port/index:查询索引信息 GET book 相当于查看 数据库表结构

    • http://ip:port/index/type/doc_id:查询指定的文档信息

    注意 咱们用的是 es 7 直接使用type 的 话 会给出警告信息 ,咱们使用 _doc 代替 type

    比如 查询指定文档信息 GET book/_doc/1 查询 book 索引中 id 为1 的文档信息

    GET book/_doc/2

    注意 咱们用的是 es 7 直接使用type 的 话 会给出警告信息 ,咱们使用 _doc 代替 type

    比如 查询指定文档信息 GET book/_doc/1 查询 book 索引中 id 为1 的文档信息

    GET book/_doc/2
    • POST请求:

      • http://ip:port/index/type/doc_id

    1. # 指定文档id的添加操作            
    2. # 如果索引还未创建 还可以创建索引
    3. POST book/_doc/2
    4. {  
    5. "name":"西游记",    
    6. "author":"吴承恩"
    7. }

    http://ip:port/index/type/_search:查询文档,可以在请求体中添加json字符串来代表查询条件。

    1. # 查询操作
    2.   POST book/_search
    3.   {
    4.     "query":{
    5.       "match": {
    6.         "name": "西游记"
    7.       }
    8.     }
    9.   }

    http://ip:port/index/type/doc_id/_update:修改文档,在请求体中指定json字符串代表修改的具体信息     注意 带 _update 的 修改 json 格式 里需要加 doc 对比本文档下面的案例说明。 

    1.   POST book/_update/1     # 修改操作
    2.   {
    3.     "doc":{
    4.       "name":"大奉打更2人",    
    5.       "author":"xxxxx2"
    6.     }
    7.   }

    PUT请求:

    http://ip:port/index:创建一个索引,也可以在请求体中指定索引的信息,类型,结构。

    1. PUT book2  # 创建一个叫 book2 的索引   执行第二次会报错
    2. # 添加或修改文档   第一次是添加(同样 索引不存在 也会创建索引) 后面再执行是修改
    3. PUT book3/_doc/1
    4. {
    5.   "name":"java"
    6. }

    http://ip:port/index/type/_mappings:代表创建索引时,指定索引文档存储的属性的信息 

            DELETE请求:

            http://ip:port/index:删除索引

    • DELETE book2     # 删除book2 索引

             http://ip:port/index/type/doc_id:删除指定的文档

    • ​DELETE book/_doc/2      删除索引book中  id 为2 的文档

    4.3 索引的操作

    4.3.1 创建一个索引

    语法如下先创建一个最简单的先不指定他的结构化数据。

    1. # 创建一个索引
    2. PUT /person
    3. {
    4.  "settings": {
    5.    "number_of_shards": 5,      # 分片 数5  
    6.    "number_of_replicas": 1    # 备份
    7. }
    8. }

     4.3.2 查看索引信息

    语法如下:去management 中查看索引信息

    Primaries 意思是分片

    Replicas 意思是备份

    Health健康状态黄色表示不太健康,因为现在es 集群中只有一台服务器备份分片没有地方存放,所以是黄色的健康状态,如果集群中有多台服务器,备份分片就可以存储在别的服务器上,避免这台服务器挂掉数据丢失问题。

    点索引的名字可以查看索引的详细信息。

    1. # 查看索引信息
    2. GET /person

    查看信息

    4.3.3 删除索引

    语法如下

    1. # 删除索引
    2. DELETE /person

    4.4 ES中Field可以指定的类型

     字符串类型

    • text:一把被用于全文检索。 将当前Field进行分词。

    • keyword:当前Field不会被分词。

    数值类型

    • scaled_float:根据一个long和scaled来表达一个浮点型,long-345,scaled-100 -> 3.45

    • half_float:精度比float小一半。

    • float:3.402823e+38 ~ 1.401298e-45(e+38表示是乘以10的38次方,e-45表示乘以10的负45次方),占用4个字节

    • double:1.797693e+308~ 4.9000000e-324 (e+308表示是乘以10的308次方,e-324表示乘以10的负324次方)占用8个字节

    • byte:取值范围为-128~127(-2的7次方到2的7次方-1),占用1个字节

    • short:取值范围为-32768~32767(-2的15次方到2的15次方-1),占用2个字节

    • integer:取值范围为-2147483648~2147483647(-2的31次方到2的31次方-1),占用4个字节

    • long:取值范围为-9223372036854774808~922337203685477480(-2的63次方到2的63次方-1),占用8个字节

    时间类型

    • date类型,针对时间类型指定具体的格式

    布尔类型

    • boolean类型,表达true和false

    二进制类型

    • binary类型暂时支持Base64 encode string

    范围类型

    • long_range:赋值时,无需指定具体的内容,只需要存储一个范围即可,指定gt,lt,gte,lte
    • integer_range:同上
    • double_range:同上
    • float_range:同上
    • date_range:同上
    • ip_range:同上

    经纬度类型

    • geo_point:用来存储经纬度的

    ip类型

    • ip:可以存储IPV4或者IPV6

    其他的数据类型参考官网:Field datatypes | Elasticsearch Guide [7.6] | Elastic

    4.5 创建索引并指定数据结构

    语法如下

    1. # 创建索引,指定数据结构
    2. PUT /book
    3. {
    4.  "settings": {
    5.    # 分片数
    6.    "number_of_shards": 5,
    7.    # 备份数
    8.    "number_of_replicas": 1
    9. },
    10.  # 指定数据结构
    11.  "mappings": {
    12.    # 类型 Type       es 7 可以把这个删了
    13.    "novel": {
    14.      # 文档存储的Field
    15.      "properties": {
    16.        # Field属性名
    17.        "name": {
    18.            # 类型
    19.          "type": "text",
    20.            # 指定分词器 # 在对这个属性做分词的时候 使用 ik分词器
    21.          "analyzer": "ik_max_word",
    22.            # 指定当前Field可以被作为查询的条件 如果为false 则不能作为查询条件
    23.          "index": true ,
    24.            # 当前field是否需要额外存储   一般设置为false 即可 不需要额外存储
    25.          "store": false
    26.       },
    27.        "author": {
    28.            # keyword 也算是字符串类型
    29.          "type": "keyword"
    30.       },
    31.        "count": {
    32.          "type": "long"
    33.       },
    34.        "on-sale": {
    35.          "type": "date",
    36.           # 时间类型的格式化方式
    37.          "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
    38.       },
    39.        "descr": {
    40.          "type": "text",
    41.            # 在对这个属性做分词的时候 使用 ik分词器
    42.          "analyzer": "ik_max_word"
    43.       }
    44.     }
    45.   }
    46. }
    47. }

    4.6 文档的操作

    文档在ES服务中的唯一标识,_index_type_id三个内容为组合,锁定一个文档,操作是添加还是修改。

    4.6.1 新建文档

    自动生成_id

    1. # 添加文档,自动生成id     不推荐这种自动生成的id
    2. POST /book/_doc
    3. {
    4.  "name": "盘龙",
    5.  "author": "我吃西红柿",
    6.  "count": 100000,
    7.  "on-sale": "2000-01-01",
    8.  "descr": "山重水复疑无路,柳暗花明又一村"
    9. }

    手动指定_id

    1. # 添加文档,手动指定id     推荐使用
    2. PUT /book/_doc/1
    3. {
    4.  "name": "红楼梦",
    5.  "author": "曹雪芹",
    6.  "count": 10000000,
    7.  "on-sale": "1985-01-01",
    8.  "descr": "一个是阆苑仙葩,一个是美玉无瑕"
    9. }

    4.6.2 修改文档

    覆盖式修改

    1. # 修改文档   覆盖式修改 如果没有指定某个属性 这个属性会被覆盖掉 覆盖没了
    2. PUT /book/novel/1
    3. {
    4.  "name": "红楼梦",
    5.  "author": "曹雪芹",
    6.  "count": 4353453,
    7.  "on-sale": "1985-01-01",
    8.  "descr": "一个是阆苑仙葩,一个是美玉无瑕"
    9. }

    doc修改方式

    1. # 修改文档,基于doc方式 不会覆盖之前的内容 指定哪一个属性 修改哪一个属性
    2. POST /book/novel/1/_update # 7 之前的写法
    3. {
    4. "doc": {
    5. # 指定上需要修改的field和对应的值
    6. "count": "1234565"
    7. }
    8. }
    9. # 现在 都这样写
    10. POST book/_update/1
    11. {
    12. "doc":{
    13. "name": "斗破苍穹"
    14. }
    15. }

    4.6.3 删除文档

    根据id删除

    1. # 根据id删除文档
    2. DELETE book/_doc/1      # 删除id 为1 的文档

    4.6.4 补充

    在kibana 可视化界面中可以看到 创建的索引信息

    五、Java操作ElasticSearch

    5.1 Java连接ES

    创建springboot工程

    导入依赖

    这里注意 springboot版本 默认了es 的 一些版本,需要咱们自己统一定义 要不然会有版本冲突 所以 在pom 文件中 统一 es 版本

    1.   <properties>
    2.        <java.version>1.8java.version>
    3.        <elasticsearch.version>7.4.2elasticsearch.version>
    4.    properties>
    5. <dependencies>
    6.    
    7.     <dependency>
    8.            <groupId>org.elasticsearchgroupId>
    9.            <artifactId>elasticsearchartifactId>
    10.            <version>7.4.2version>
    11.        dependency>
    12.    
    13.    
    14.   <dependency>
    15.            
    16.            <groupId>org.elasticsearch.clientgroupId>
    17.            <artifactId>elasticsearch-rest-high-level-clientartifactId>
    18.            <version>7.4.2version>
    19.        dependency>
    20.    
    21.    <dependency>
    22.         <groupId>junitgroupId>
    23.         <artifactId>junitartifactId>
    24.         <version>4.12version>
    25.     dependency>
    26.    
    27.     <dependency>
    28.        <groupId>org.projectlombokgroupId>
    29.         <artifactId>lombokartifactId>
    30.         <version>1.16.22version>
    31.    dependency>
    32. dependencies>

    创建配置类,测试连接ES

    1. package com.ymk.esdemo.config;
    2. import org.apache.http.HttpHost;
    3. import org.elasticsearch.client.RequestOptions;
    4. import org.elasticsearch.client.RestClient;
    5. import org.elasticsearch.client.RestClientBuilder;
    6. import org.elasticsearch.client.RestHighLevelClient;
    7. import org.springframework.context.annotation.Bean;
    8. import org.springframework.context.annotation.Configuration;
    9. @Configuration
    10. public class ElasticSearchConfig {
    11.    //RequestOptions   这个类 主要封装了 访问 ES 的 一些头信息   一些 设置信息
    12.    public static final RequestOptions COMMON_OPTIONS;
    13.    static {
    14.        // 请求设置项
    15.        RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
    16. //       builder.addHeader("Authorization","Bearer"+TOKEN);
    17. //       builder.setHttpAsyncResponseConsumerFactory(new HttpAsyncResponseConsumerFactory
    18. //               .HeapBufferedResponseConsumerFactory(30*1024*1024*1024));
    19.        COMMON_OPTIONS = builder.build();
    20.   }
    21.    @Bean
    22.    public RestHighLevelClient esRestClient(){
    23.        RestClientBuilder builder = null;
    24.        builder = RestClient.builder(new HttpHost("192.168.5.205",9200,"http"));
    25.        RestHighLevelClient client = new RestHighLevelClient(builder);
    26.        //RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("192.168.56.10", 9200, "http")));
    27.        return client;
    28.   }
    29. }
    30. // 测试 能不能得到 RestHighLevelClient
    31.    @SpringBootTest
    32. class EsdemoApplicationTests {
    33.    @Resource
    34.    private RestHighLevelClient client;
    35.    @Test
    36.    void contextLoads() {
    37.        System.out.println(client);
    38.   }
    39. }    

    5.2 Java操作索引

    5.2.1 创建索引

    代码如下

       
    1. /**
    2.     * 索引的创建
    3.     *
    4.     * */
    5.        /**
    6.         * {
    7.         * "properties":{
    8.         *     "name":{
    9.         *         "type":"text"
    10.         *     },
    11.         *     "age":{
    12.         *         "type":"integer"
    13.         *     },
    14.         *     "birthday":{
    15.         *         "type":"date",
    16.         *         "format":"yyyy-MM-dd"
    17.         *     }
    18.         * }
    19.         *
    20.         * }
    21.         *
    22.         * */
    23.    @Test
    24.    public void demo1() throws IOException {
    25.        // 创建索引
    26.        String index = "person";
    27.        //1. 准备关于索引的settings
    28.        Settings.Builder settings = Settings.builder()
    29.               .put("number_of_shards", 3)
    30.               .put("number_of_replicas", 1);
    31.        //2. 准备关于索引的结构mappings
    32.        XContentBuilder mappings = JsonXContent.contentBuilder()
    33.               .startObject()        // 和 endObject 成对出现
    34.               .startObject("properties")
    35.               .startObject("name")
    36.               .field("type","text")
    37.               .endObject()
    38.               .startObject("age")
    39.               .field("type","integer")
    40.               .endObject()
    41.               .startObject("birthday")
    42.               .field("type","date")
    43.               .field("format","yyyy-MM-dd")
    44.               .endObject()
    45.               .endObject()
    46.               .endObject();
    47.        //3. 将settings和mappings封装到一个Request对象
    48.        // 不同的操作 准备的request 对象不一样 与下文对比
    49.        CreateIndexRequest request = new CreateIndexRequest(index)
    50.               .settings(settings)
    51.               .mapping(mappings);// 如果是6版本 还需要在这个方法指定type                     //.mapping(type,mappings)
    52.        //4. 通过client对象去连接ES并执行创建索引
    53.        // 通过client 对象 把上面准备的 request 对象 发到es执行  
    54.        CreateIndexResponse resp = client.indices().create(request, RequestOptions.DEFAULT);
    55.        //5. 输出
    56.        System.out.println("resp:" + resp.toString());
    57.   }

    5.2.2 检查索引是否存在

    代码如下

    1. /**
    2. * 判断 索引是否存在
    3.     * */
    4.    @Test
    5.    public void demo2() throws IOException {
    6.        //1. 准备request对象
    7.        String index = "person";
    8.        GetIndexRequest request = new GetIndexRequest(index);
    9.        request.indices();
    10.        //2. 通过client去操作
    11.        boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
    12.        //3. 输出
    13.        System.out.println(exists);
    14.   }

    5.2.3 删除索引

    代码如下

    1. @Test
    2. public void delete() throws IOException {
    3.    //1. 准备request对象
    4.    DeleteIndexRequest request = new DeleteIndexRequest();
    5.    request.indices(index);
    6.    //2. 通过client对象执行
    7.    AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
    8.    //3. 获取返回结果
    9.    System.out.println(delete.isAcknowledged());
    10. }

    5.3 Java操作文档

    5.3.1 添加文档操作

    代码如下

    添加fastjson 依赖,  jackson 也可以 用法大致一样 

    1. <dependency>
    2.            <groupId>com.alibabagroupId>
    3.            <artifactId>fastjsonartifactId>
    4.            <version>1.2.31version>
    5.        dependency>
    1.    
    2. // 创建实体类
    3. @Data
    4. @AllArgsConstructor
    5. @NoArgsConstructor
    6. @ToString
    7. public class Person {
    8.    private Integer id;
    9.    private String name;
    10.    private Integer age;
    11.    @JSONField(format = "yyyy-MM-dd")     // fastjson 转换对象时 对日期类型字段的 格式转换
    12.    private Date birthday;
    13. }
    14. // 测试方法    
    15. /**
    16.     * 添加文档
    17.     *
    18.     * */
    19.    @Test
    20.    public void demo4() throws IOException {
    21.        String index = "person";
    22.            //1. 准备一个json数据
    23.            Person person = new Person(1,&#
  • 相关阅读:
    C#中使用CAS实现无锁算法
    QCC51XX-QCC30XX系列开发教程(实战篇) 之 12.5-空间音频用开发板调试配置说明
    FPGA工程师面试——基础概念问题整理
    企业实现员工聊天和转账行为的实时监管
    gltf和glb格式模型用什么软件处理
    数据标准化算法介绍—数据建模工具
    重生之我是一名程序员 33
    springboot农机电招平台springboot37
    Java-堆和栈的概念和区别-1
    HCIA 访问控制列表ACL
  • 原文地址:https://blog.csdn.net/m0_71012114/article/details/127740267