Java阶段四Day11

Java阶段四Day11

文章目录

  • Java阶段四Day11
    • Spring AOP
    • Elasticsearch
      • 1. 关于各种数据库的使用
      • 2. 关系型数据库中的索引
      • 3. 安装与启动elasticsearch
      • 4. 访问elasticsearch
      • 5. 使用elasticsearch分词
      • 6. elasticsearch文档的相关概念
      • 7. 使用elasticsearch添加数据
        • 7.1. 添加文档
        • 7.2. 查看文档
        • 7.3. 修改文档
        • 7.4. 删除
      • 8. elasitcsearch中的字段的数据类型
      • 9. 搜索
        • 9.1. 准备测试数据
        • 9.2. 简单的搜索
        • 9.3. 高级搜索
      • 10. 基于Spring Boot的elasticsearch编程
      • 10.1. 添加依赖
        • 10.2. 处理文档数据
        • 10.3. 编写数据访问接口

Spring AOP

AOP:面向切面编程

注意:AOP并不是Spring原创的技术,也不是Spring的独家技术,而是源自AspectJ,只是Spring很好的支持了AOP。

AOP技术主要解决了“横切关注”的相关问题,也就是“若干个不同的方法都需要执行相同的任务”的问题!

在许多框架中,都通过AOP技术实现了对应的功能,例如:

  • 在Spring JDBC中,使用AOP实现了事务管理

    try {
        开启事务
        执行连接点:你的业务方法
        提交事务
    } catch (RuntimeException e) {
    	回滚事务
    }
    
  • 在Spring MVC框架中,使用AOP处理了异常

  • 在Spring Security框架,使用AOP检查权限

假设存在需求:统计当前项目中所有Service方法的执行耗时。

在Spring Boot项目中使用AOP需要添加依赖:

<!-- Spring Boot支持AOP的依赖项 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

然后:


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

/**
 * 统计所有Service方法执行耗时的切面类
 *
 * @author java@tedu.cn
 * @version 1.0
 */
@Aspect
@Component
public class TimerAspect {

    @Around("execution(* cn.tedu.tea.admin.server..service.*.*(..))")
    public Object xx(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.currentTimeMillis();
        Object proceedResult = pjp.proceed();
        long end = System.currentTimeMillis();
        System.out.println("执行耗时:" + (end - start));
        return proceedResult;
    }

}

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * 统计所有Service方法执行耗时的切面类
 *
 * @author java@tedu.cn
 * @version 1.0
 */
@Slf4j
@Aspect // 标记当前类是一个切面类
@Component // 标记当前类是一个组件类,则Spring会进行处理
public class TimerAspect {

    // 连接点(JoinPoint):程序执行过程中的某个节点,可能是某个方法的调整,或是某个方法抛出了异常
    // 切入点(PointCut):匹配连接点的表达式
    // -------------------------------------------------------------------
    // 通知(Advice)注解:
    // @Around:环绕,可以包裹连接点的执行,所以,你可以在执行连接点之前和之后编写你所需的代码
    // @Before:在执行连接点之前
    // @After:在执行连接点之后
    // @AfterThrowing:在抛出异常之后
    // @AfterReturning:在成功返回之后
    // -------------------------------------------------------------------
    // 各通知的执行点大致是以下这样:
    // @Around开始
    // try {
    //      @Before
    //      执行连接点
    //      @AfterReturning
    // } catch (Throwable e) {
    //      @AfterThrowing
    // } finally {
    //      @After
    // }
    // @Around结束
    // -------------------------------------------------------------------
    // 切入点表达式:匹配某些方法
    // 可以使用通配符:
    // - 星号(*):任意有且仅有1次匹配
    // - 2个连接的小数点(..):任意n次匹配,仅能用于包名和参数列表
    //                 ↓ 返回值类型
    //                   ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 包名
    //                                                  ↓ 类名
    //                                                    ↓ 方法名
    //                                                      ↓↓ 参数列表
    // 在切入点表达式中,在返回值类型声明的左侧,还可以指定修饰符,修饰符是可选的
    // 如果没有显式的指定修饰符,则无论什么修饰符都可以匹配
    // 其实,其它部分也是如此,例如,如果没有指定包名,则无视匹配的类在哪个包下
    // 注意:注解是典型的修饰符
    // 注意:无论是注解,还是返回值、参数,只要不是基本数据类型、java.lang包下的类型,都必须使用全限定名
    @Around("execution(* cn.*.tea.admin.server..service.*.*(..))")
    //     ↓↓↓↓↓↓ 使用@Around时必须声明为ProceedingJoinPoint对象调用proceed()返回的结果
    //            ↓↓↓↓↓ 自定义的方法名
    //                  ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 使用@Around时必须是ProceedingJoinPoint类型
    //                                           ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 必须抛出
    public Object timer(ProceedingJoinPoint pjp) throws Throwable {
        log.trace("TimerAspect.timer()开始执行");
        // 获取连接点信息
        String targetClassName = pjp.getTarget().getClass().getName(); // 类型名
        String signatureName = pjp.getSignature().getName(); // 方法名
        Object[] args = pjp.getArgs(); // 参数列表
        System.out.println("连接点(方法)所属的类的名称:" + targetClassName);
        System.out.println("连接点(方法)的名称:" + signatureName);
        System.out.println("连接点(方法)的参数列表:" + Arrays.toString(args));
        // 获取起始时间
        long start = System.currentTimeMillis();
        // 调用ProceedingJoinPoint参数对象的proceed()方法,表示执行连接点,即调用了匹配到的方法
        // 注意-1:调用proceed()方法的异常,必须抛出,不可以简单的try...catch(除非在catch中再抛出异常)
        // 注意-2:调用proceed()方法时返回的结果,表示对应的Service方法的返回值,必须作为当前切面方法的返回值
        Object proceedResult = pjp.proceed();
        // 获取结束时间
        long end = System.currentTimeMillis();
        // 输出
        System.out.println("执行耗时:" + (end - start));
        log.trace("TimerAspect.timer()执行结束,即将返回");
        return proceedResult;
    }

}

关于SpringAOP的更多知识可看这篇文章:Spring AOP讲解及实例

Elasticsearch

1. 关于各种数据库的使用

关于MySQL:是关系型数据库,能清楚的表示数据之间的关系,并且,是基于磁盘存储的,可以使用相对较低的成本存储大量的数据

关于Redis:是基于K-V结构的在内存中读写数据的数据库(虽然也会自动同步到磁盘),能够明显的提高查询效率(通常设计预期不低于10万QPS),进而还可以保护关系型数据库,并且,通常是使用专门的服务器或集群,也可以作为整个集群中的共享内存资源

关于elasticsearch:用于解决搜索问题的非关系型文档数据库

2. 关系型数据库中的索引

在关系型数据库中,索引(index)是一种单独的、物理层面的对数据库中的一列或多列的值进行排序检索的一种数据结构。

如果没有做任何优化的处理,当MySQL这类数据库中的数据量较多时,查询效率会非常低下,这是因为在执行查询时,MySQL会把当前表中所有的数据全部检查一遍,检查每条数据是否匹配当前的查询规则!另外,MySQL是基于磁盘存储的,数据不会非常整齐的集中存储在磁盘的某个位置,而是散列的分布的磁盘的不同位置,例如:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yg4Plz7I-1688551201196)(assets\image-20230705101201977.png)]

所以,在查询时,会需要频繁的执行IO操作,最终,实际表现查询效率非常低!

在MySQL中,创建索引的简单语法是:

CREATE INDEX index_name ON table_name (column_name[, column_name_2 ...]);

例如:

CREATE INDEX idx_username ON account_user (username);

对于某张表的某个字段的索引,只需要创建1次即可!

当创建索引后,索引对应的列的查询效率都可以在毫秒级完成!

注意:在创建索引时,表中的数据越多,创建索引的耗时越多!

删除索引的语法格式是:

DROP INDEX index_name ON table_name;

例如:

DROP INDEX idx_username ON account_user;

在创建索引时,MySQL会将对应字段的数据进行排序,并在索引中记录下每条数据的位置信息,所以,索引就相当于是“书的目录”,后续,当需要查询时,会先翻“书的目录”,找出数据对应的“页码”,并直接翻到对应的那一页,就能把数据全部找出来!所以,整体效率非常之高!

索引的本质是一种B+Tree结构(是一种树型结构)的数据,在MySQL中,InnoDB存储引擎中页的大小是16KB,如果使用BIGINT类型的主键,每个主键需要占用8字节,在B+Tree中的指针是4~8字节,每个指针与主键形成一个节点,则每个节点将占用最多16字节,每页最少可以存储1024个节点,深度为3的B+Tree最多可以存储1024 * 1024 * 1024个节点,大约是1000 * 1000 * 1000 = 1000000000个节点(10亿),所以,每个B+Tree可以维护约10亿个节点,如果表中的数据量不超过10亿条,都只需要最多执行3次IO操作,就可以找出数据的位置。

在数据库,即使你没有显式的创建索引,某些字段的查询效率可能也非常高,因为索引还有其它种类,包括:

  • PRIMARY KEY:主键索引
  • UNIQUE:唯一索引
  • INDEX:普通索引
  • FULLTEXT:全文索引

基于索引的特性,使用时,必须注意:

  • 索引不会包含有NULL值的列
  • 数据量非常少的表没有必要创建索引,例如绝大部分字典表,或数据量不多且修改频率也非常低的表也没有必要创建索引,例如资讯平台的“栏目”或“类别”、小型应用中“用户的角色”
  • 数据经常变化的字段不要创建索引,因为会频繁的更新索引,导致更新效率低下
  • 查询时需要计算字段值时,索引是无效的,例如:where age + 10 > 30时,age列的索引是无效的
  • 左侧的模糊查询无法使用索引,因为索引是基于对这一列的数据进行排序得到的
    • 其实,在开发实践中,所有模糊查询都是不允许使用的

除了以上限制以外,不同的企业的开发规范可能提出更高的要求:

  • 类型为text的字段不允许使用索引
  • 类型为varchar且字段值可能很长的字段,也不允许使用索引
  • 其它

3. 安装与启动elasticsearch

无论是哪个操作系统,只需要下载elasticsearch的压缩包即可,将其解压,执行bin目录下的elasticsearch即可启动elasticsearch服务:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ixE86Lo6-1688551201197)(assets\image-20230705141026096.png)]

启动成功后,看到的结果大致是:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hdi9DnNc-1688551201198)(assets\image-20230705141117661.png)]

在使用elasticsearch的过程中,以上窗口不可以关闭!

启动成功后,你可以通过浏览器访问 http://localhost:9200,结果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b3L8uD8e-1688551201199)(assets\image-20230705141253272.png)]

4. 访问elasticsearch

elasticsearch提供的访问方式是基于RESTful的,你可以使用任何一个可以提交REST请求的工具来访问elasticsearch,例如常见的测试工具PostMan等。

在IntelliJ IDEA中,你可以创建以.http为扩展名的HttpRequest文件,通过这类文件来提交REST请求,例如:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZxUCoGTK-1688551201200)(assets\image-20230705142113575.png)]

然后,在文件中编写请求:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-21tWQq1T-1688551201201)(assets\image-20230705142236387.png)]

直接点击请求左侧的绿色小箭头即可发起请求,执行效果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PDUf8RrZ-1688551201201)(assets\image-20230705142416281.png)]

5. 使用elasticsearch分词

向 http://localhost:9200/_analyze 提交请求即可分词,请求参数必须是名为text的,参数值就是你希望分词的词组或词句,例如:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8q6Hdiqn-1688551201202)(assets\image-20230705143417016.png)]

在同一个.http文件中,可以编写多个请求,但是,后续的请求的代码必须使用 ### 和前序的请求分开,不能只使用1个 #

也可以对中文进行分词,但是,默认的分词对中文的支持非常不好,它只会将每个汉字作为一个词!

示例代码:

### 简单的分词:中文
GET http://localhost:9200/_analyze
Content-Type: application/json

{
  "text": "很高兴认识你!"
}

可以在elasticsearch中安装插件,以更好的支持中文的分词,经典的中文分词插件就是ik分词器。

你只需要找到elasticsearch文件夹下的plugins文件夹(如下图所示):

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j93N1d92-1688551201203)(assets\image-20230705144408822.png)]

然后,将IK分词器的文件夹粘贴到plugins的子级即可,并且,你可以自由的修改IK分词器文件夹的名称,例如:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8YJYOUne-1688551201204)(assets\image-20230705144540764.png)]

以上配置完成后,需要重启elasticsearch才会应用新的分词器!

接下来,在提交请求时,可以在请求参数列表中添加analyzer参数,取值可以是IK分词器中的ik_smartik_max_word,例如:

### 使用IK的分词:智能
GET http://localhost:9200/_analyze
Content-Type: application/json

{
  "analyzer": "ik_smart",
  "text": "很高兴认识你!"
}

### 使用IK的分词:最大词量(最细粒度)
GET http://localhost:9200/_analyze
Content-Type: application/json

{
  "analyzer": "ik_max_word",
  "text": "很高兴认识你!"
}

使用IK分词器时,还可以自造词!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mtfvl6Rg-1688551201204)(assets\image-20230705152018871.png)]

6. elasticsearch文档的相关概念

索引(index / indices)

  • 相当于MySQL中的Database

类型(type / types)

  • 相当于MySQL中的Table,可以自行创建“类型”,或,如果不关心“类型”,则使用_doc表示类型名

文档(document / documents)

  • 相当于MySQL中的一行行的数据,在elasticsearch中每个数据都是由JSON格式组织的

字段(field / fields)

  • 相当于MySQL中的Column

7. 使用elasticsearch添加数据

7.1. 添加文档

添加文档(使用elasticsearch随机生成的ID)

请求URL的格式:

POST http://localhost:9200/{索引名}/{类型名}

提示:添加文档时,如果索引不存在,会自动创建索引;如果类型不存在,会自动创建类型!

请求示例:

### 添加文档(新增数据),将随机生成此数据在ES中的ID
POST http://localhost:9200/index_crud/_doc
Content-Type: application/json

{
  "id": 1,
  "title": "这是放在ES中的第1篇文章",
  "sort": 80,
  "gmtCreate": "2023-07-01"
}

添加文档(新增数据),并自行指定ID

请求URL的格式(此处对ID值并没有严格的要求):

PUT http://localhost:9200/{索引名}/{类型名}/{文档ID}

请求示例:

### 添加文档(新增数据),并自行指定ID,此处对ID值并没有严格的要求
PUT http://localhost:9200/index_crud/_doc/No9527
Content-Type: application/json

{
  "id": 9527,
  "title": "这是放在ES中的第2篇文章",
  "sort": 90,
  "gmtCreate": "2023-07-02"
}

7.2. 查看文档

查看当前索引中的所有文档

请求URL的格式:

GET http://localhost:9200/{索引名}/_search

请求示例:

### 查看当前索引中的所有文档
GET http://localhost:9200/index_crud/_search

根据ID访问文档

请求URL的格式:

GET http://localhost:9200/{索引名}/_doc/{文档ID}

提示:如果是elasticsearch自动生成的ID,你可以通过“查看所有文档”来获取ID值,或者,此前添加文档时,返回的结果中也会包含ID值。

请求示例:

### 根据ID访问文档(此前添加文档时使用的自定义IDGET http://localhost:9200/index_crud/_doc/No9527

7.3. 修改文档

修改文档【1】

请求URL的格式:

PUT http://localhost:9200/{索引名}/_doc/{文档ID}

提示:以上请求与“指定ID的添加文档”是相同的!

注意:此类操作会使用请求参数替换原有的整个数据,如果原数据有5个属性,请求参数只有2个属性,执行后,数据将只有本次请求的2个属性!

请求示例:

PUT http://localhost:9200/index_crud/_doc/No9527
Content-Type: application/json

{
  "id": 9527,
  "title": "这是放在ES中的第2篇文章",
  "sort": 90,
  "gmtCreate": "2023-07-02"
}

修改文档【2】

请求URL的格式:

POST http://localhost:9200/{索引名}/_doc/{文档ID}/_update

提示:这种修改文档的方式只会修改原数据中与本次请求参数对应的属性

注意:如果原数据中没有本次请求的参数属性,则会在原数据上添加新的属性!

请求示例:

POST http://localhost:9200/index_crud/_doc/No9527/_update
Content-Type: application/json

{
  "doc": {
    "commentCount": 637
  }
}

7.4. 删除

根据ID删除文档

请求URL的格式:

DELETE http://localhost:9200/{索引名}/{类型名}/{文档ID}

注意:如果尝试删除的文档不存在,则会响应404错误!

请求示例:

DELETE http://localhost:9200/index_crud/_doc/No9527

删除整个索引

请求URL的格式:

DELETE http://localhost:9200/{索引名}

注意:将会删除这个索引中的所有类型及各类型中的数据!

注意:如果尝试删除的索引不存在,则会响应404错误!

请求示例:

DELETE http://localhost:9200/index_crud

8. elasitcsearch中的字段的数据类型

在elasticsearch中,文档的各个字段都是有数据类型的,大致有:

  • 字符串类型:textkeyword
    • text类型被处理时,默认会被分词
      • 默认类型
    • keyword类型被处理时,默认不会被分词
  • 数值类型:integerlong

当向elasticsearch中添加文档时,如果对应的索引没有设置数据类型,则会自动设置数据类型!

可以查询索引信息,来观察各字段的数据类型!请求URL的格式为:

### 查看索引的基本信息
GET http://localhost:9200/{索引名}

请求示例:

### 查看索引的基本信息
GET http://localhost:9200/index_search

也可以专门的创建索引,并在创建时指定各字段的数据类型,请求方式大致是:

PUT http://localhost:9200/{索引名}
Content-Type: application/json

{
	"mappings": {
		"properties": {
			"{字段名1}": {
				"type": "{数据类型1}"
			},
			"{字段名2}": {
				"type": "{数据类型2}"
			},
			...
			"{字段名n}": {
				"type": "{数据类型n}"
			}
		}
	}
}

请求示例:

### 创建索引,并配置各字段的数据类型
PUT http://localhost:9200/index_search
Content-Type: application/json

{
  "mappings": {
    "properties": {
      "id": {
        "type": "long"
      },
      "title": {
        "type": "text"
      },
      "desc": {
        "type": "keyword"
      },
      "sort": {
        "type": "integer"
      },
      "price": {
        "type": "integer"
      }
    }
  }
}

9. 搜索

9.1. 准备测试数据

预计的测试数据是:

idtitledescsortprice
1散装龙井性价比之王150200
2龙井礼盒套装超值套装160668
3新上架铁观音新茶上市120370
4武夷大红袍经典红茶130988
5茉莉花茶小清新190120

将以上测试数据存入到名为index_search索引中,则代码为:

### 添加测试数据-1
PUT http://localhost:9200/index_search/_doc/1
Content-Type: application/json

{
  "id": 1,
  "title": "散装龙井",
  "desc": "性价比之王",
  "sort": 150,
  "price": 200
}

### 添加测试数据-2
PUT http://localhost:9200/index_search/_doc/2
Content-Type: application/json

{
  "id": 2,
  "title": "龙井礼盒套装",
  "desc": "超值套装",
  "sort": 160,
  "price": 668
}

### 添加测试数据-3
PUT http://localhost:9200/index_search/_doc/3
Content-Type: application/json

{
  "id":3,
  "title": "新上架铁观音",
  "desc": "新茶上市",
  "sort": 120,
  "price": 370
}

### 添加测试数据-4
PUT http://localhost:9200/index_search/_doc/4
Content-Type: application/json

{
  "id": 4,
  "title": "武夷大红袍",
  "desc": "经典红茶",
  "sort": 130,
  "price": 988
}

### 添加测试数据-5
PUT http://localhost:9200/index_search/_doc/5
Content-Type: application/json

{
  "id": 5,
  "title": "茉莉花茶",
  "desc": "小清新",
  "sort": 190,
  "price": 120
}

9.2. 简单的搜索

请求URL的格式:

GET http://localhost:9200/{索引名}/_search?q={字段名:关键字}

注意:执行以上搜索时,会自动对关键字进行分词,例如,关键是“套装”时,“散装”也会出现在结果中,因为会对“套装”进行分词,得到“套装”、“套”、“装”这些词,而“散装”也包含了“装”,所以,会出现在结果中!

请求示例:

### 搜索:按照title的“套装”进行搜索
GET http://localhost:9200/index_search/_search?q=title:套装

### 搜索:按照desc的“红茶”进行搜索
GET http://localhost:9200/index_search/_search?q=desc:红茶

注意:执行以上搜索时,如果搜索的字段是text类型,会自动对关键词进行分词,如果字段是keyword,则不会分词,仅有完全匹配的数据才会被搜索到!

9.3. 高级搜索

### 搜索:简单的自定义query搜索,如果不写query,相当于SQL里没有where,则搜索全部数据,或者,将match部分配置为:"match_all": {}
GET http://localhost:9200/index_search/_search
Content-Type: application/json

{
  "query": {
    "match": {
      "title": "套装"
    }
  }
}

### 搜索:多个条件的搜索,must >>> AND / should >>> OR / must_not >>> !=
GET http://localhost:9200/index_search/_search
Content-Type: application/json

{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "title": "套装"
          }
        },
        {
          "match": {
            "desc": "超值套装"
          }
        }
      ]
    }
  }
}

### 搜索:指定查询字段列表的搜索
GET http://localhost:9200/index_search/_search
Content-Type: application/json

{
  "query": {
    "match_all": {}
  },
  "_source": [
    "id",
    "title",
    "price"
  ]
}

### 搜索:指定排序规则的搜索,通过与query同级的sort属性来配置规则,如果希望升序,则字段的属性为空对象即可
GET http://localhost:9200/index_search/_search
Content-Type: application/json

{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "price": {},
      "id": {
        "order": "desc"
      }
    }
  ]
}

### 搜索:分页搜索,通过与query同级的from属性表示从第几条开始,0表示第1条,以此类推,另外再通过size属性表示搜索多少条数据
GET http://localhost:9200/index_search/_search
Content-Type: application/json

{
  "query": {
    "match_all": {}
  },
  "from": 2,
  "size": 2
}

### 搜索:高亮显示,通过与query同级的highlight标签进行配置,会在搜索结果中生成与数据结果同级的highlight对象,默认会在匹配的文本上添加em标签
GET http://localhost:9200/index_search/_search
Content-Type: application/json

{
  "query": {
    "match": {
      "title": "套装"
    }
  },
  "highlight": {
    "fields": {
      "title": {}
    },
    "pre_tags": "<font style='color: red;'>",
    "post_tags": "</font>"
  }
}

10. 基于Spring Boot的elasticsearch编程

10.1. 添加依赖

<!-- Spring Boot支持elasticsearch编程的依赖项 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

10.2. 处理文档数据

在基于Spring Data Elasticsearch的开发时,需要在存入/读取时使用的数据类型上添加相关注解:

  • @Document:添加在类上,通过此注解的indexName属性配置此类数据在elasticsearch中的索引名称
  • @Id:添加在类中被作为主键的属性上,表示此属性的值将作为数据在elasticsearch中的ID
  • @Field:添加在类中不被作为主键的属性上,此注解并不是必须的,即使没有在属性上添加此注解进行配置,后续框架和elasticsearch也能自动处理数据类型,重点考虑那些会被用于搜索匹配的属性,特别是字符串类型的,到底配置为@Field(type = FieldType.Text)还是@Field(type = FieldType.Keyword)

示例:

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * 用于处理搜索功能的文章数据的VO类
 *
 * @author java@tedu.cn
 * @version 1.0
 */
@Data
@Document(indexName = "article") // http://localhost:9200/article
public class ArticleSearchVO implements Serializable {

    /**
     * 数据ID
     */
    @Id
    private Long id;
    /**
     * 作者ID
     */
    private Long authorId;
    /**
     * 作者名字
     */
    private String authorName;
    /**
     * 标题
     */
    @Field(type = FieldType.Text)
    private String title;
    /**
     * 摘要
     */
    @Field(type = FieldType.Text)
    private String brief;
    /**
     * 排序序号
     */
    private Integer sort;
    /**
     * 封面图
     */
    private String coverUrl;
    /**
     * 顶数量
     */
    private Integer upCount;
    /**
     * 踩数量
     */
    private Integer downCount;
    /**
     * 浏览量
     */
    private Integer clickCount;
    /**
     * 评论量
     */
    private Integer commentCount;
    /**
     * 数据创建时间
     */
    private LocalDateTime gmtCreate;
    /**
     * 数据最后修改时间
     */
    private LocalDateTime gmtModified;

}

10.3. 编写数据访问接口

在基于Spring Boot的项目中,添加了spring-boot-starter-data-elasticsearch后,当需要处理elasticsearch编程时,只需要自定义接口,实现Spring Data框架中的Repository接口即可,实现接口时必须指定2个泛型,第1个是文档对应数据类型,第2个是主键的数据类型,例如:

public interface IArticleSearchRepository extends Repository<ArticleSearchVO, Long> {
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/36428.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QT登录界面

1.效果图 2.代码 #include "widget.h" #include "ui_widget.h" #include <QApplication> #include <QWidget> #include <QtWidgets>Widget::Widget(QWidget *parent): QMainWindow(parent), ui(new Ui::Widget) {ui->setupUi(this);…

【CSS】浮动

&#x1f4dd;个人主页&#xff1a;爱吃炫迈 &#x1f48c;系列专栏&#xff1a;HTMLCSS &#x1f9d1;‍&#x1f4bb;座右铭&#xff1a;道阻且长&#xff0c;行则将至&#x1f497; 文章目录 浮动浮动的规则浮动的案例浮动的清除 浮动 float属性可以指定一个元素应沿其容器的…

deeplabv3+源码之慢慢解析 第二章datasets文件夹(1)voc.py--voc_cmap函数和download_extract函数

系列文章目录&#xff08;更新中&#xff09; 第一章deeplabv3源码之慢慢解析 根目录(1)main.py–get_argparser函数 第一章deeplabv3源码之慢慢解析 根目录(2)main.py–get_dataset函数 第一章deeplabv3源码之慢慢解析 根目录(3)main.py–validate函数 第一章deeplabv3源码之…

亚马逊云科技推出的一项完全托管的生成式AI服务——Amazon Bedrock

在全球生成式AI浪潮兴起之际&#xff0c;以“智联世界&#xff0c;生成未来”为主题的2023世界人工智能大会&#xff08;WAIC 2023&#xff09;于7月6日在上海世博中心拉开帷幕。大会首日&#xff0c;亚马逊云科技携生成式AI产品Amazon Bedrock亮相大会现场&#xff0c;亚马逊云…

Linux发行版Gentoo被发现有漏洞,在SQL注入方面存在安全风险

近日有消息表明&#xff0c;Gentoo Linux发行版中存在漏洞CVE-2023-28424&#xff0c;并且极有可能被黑客利用该漏洞进行SQL注入攻击。 据悉&#xff0c;研究人员从 GentooLinux的Soko搜索组件中找到了这个漏洞&#xff0c;并且该漏洞的CVSS风险评分为 9.1&#xff0c;属于特别…

使用Pytorch加载预训练模型及修改网络结构

Pytorch有自带的训练好的AlexNet、VGG、ResNet等网络架构。详见官网 1.加载预训练模型 import torch import torchvision import torch.nn as nn import torch.optim as optim import torch.nn.functional as F import torchvision.transforms as transforms import torchvis…

【QQ好友列表-设置HeaderView Objective-C语言】

一、咱们一起来看 刚才咱们是不是给大家说到 创建好模型了 是不是单元格,我们需要自定义单元格了 自定义单元格的步骤: 我相信大家现在脑子里,应该有那个代码的思路了吧 1)首先,是不是要新建一个类型啊 这个类型应该建在哪个里面 是不是应该建在我们的View里面 View…

linux常见指令下

接下来我们就聊聊linux的后面十条指令。 一:echo 作用是往显示器输出内容&#xff0c;和printf类型&#xff0c;但是该指令最核心的是与之相关的一些概念 概念1.输出重定向&#xff1a; echo不仅可以向显示打印内容&#xff0c;还可以向文件输出内容&#xff0c;本应该输出到…

图片视频抹除算法总结Inpaint

基本是从图片抹水印和视频抹水印两个方向 Video Inpainting&#xff1a;https://paperswithcode.com/task/video-inpaintingImage Inpainting&#xff1a;https://paperswithcode.com/task/image-inpainting 请根据目录查看 图片 Partial Conv 部分卷积层 源自于Image In…

人工智能时代如何加强网络安全

人工智能正在为软件开发人员赋予以前被认为难以想象的新能力。新的生成式人工智能可以提供复杂、功能齐全的应用程序、调试代码或使用简单的自然语言提示添加内嵌注释。 它已准备好以指数方式推进低代码自动化。但与此同时&#xff0c;新一代人工智能可能会为不良行为者提供帮…

vue中控制element表格列的显示与隐藏

背景 根据‘执行进度计算方式’的单选框里面的选项不同&#xff0c;展示不同的column 按最小制剂单位统计: 按含量统计: 实现方式 就是拿到选项框里面的值&#xff0c;再根据里面的值来判断哪些column显示和隐藏&#xff1b;关于显示和隐藏可以设置变量&#xff1b; <…

比对Excel数据

以a个为准绳比对b表数据&#xff0c;添加比对结果列输出。 (本笔记适合初通 Python 的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教程》&#xff0c;不仅仅是基础那么…

训练自己的ChatGPT 语言模型(一).md

0x00 Background 为什么研究这个&#xff1f; ChatGPT在国内外都受到了广泛关注&#xff0c;很多高校、研究机构和企业都计划推出类似的模型。然而&#xff0c;ChatGPT并没有开源&#xff0c;且复现难度非常大&#xff0c;即使到现在&#xff0c;没有任何单位或企业能够完全复…

【内控版】BLM 战略方法论:战略意图篇

目录 介绍 战略意图 专栏列表 详细内容 配图 介绍 欢迎大家继续来到华为战略方法论的系列内容。 今天就来讲讲 BLM 模型中的战略意图篇。 战略意图在 BLM 模型中的位置,大家可以看这张图。 战略意图</

Redis 主从复制 哨兵 集群

Redis 主从复制 哨兵 集群 一、Redis 主从复制1.1 Redis 主从复制介绍1.2 主从复制的作用1.3 主从复制的流程 二、搭建Redis 主从复制2.1 安装 Redis2.2 创建redis工作目录2.3 环境变量2.4 定义systemd服务管理脚本2.5 修改 Redis 配置文件&#xff08;Master节点操作&#xff…

基于TF-IDF+Tensorflow+PyQt+孪生神经网络的智能聊天机器人(深度学习)含全部Python工程源码及模型+训练数据集

目录 前言总体设计系统整体结构图系统流程图孪生神经网络结构图 运行环境Python 环境TensorFlow 环境 模块实现1. 数据预处理2. 创建模型并编译3. 模型训练及保存4. 模型应用 系统测试1. 训练准确率2. 测试效果3. 模型生成 工程源代码下载其它资料下载 前言 本项目利用TF-IDF&…

Microsoft Remote Desktop for mac安装教程

适用于Mac的Microsoft远程桌面测试版&#xff01;Microsoft Remote Desktop Beta for Mac是一种远程工具&#xff0c;允许用户从Mac远程访问基于Windows的计算机。使用此工具&#xff0c;用户可以随时随地使用Mac连接到远程桌面、应用程序和资源。 Microsoft Remote Desktop B…

【玩转Linux操作】一文带你明白Shell的判断,循环语句

&#x1f38a;专栏【玩转Linux操作】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【如愿】 大一同学小吉&#xff0c;欢迎并且感谢大家指出我的问题&#x1f970; 文章目录 &#x1f354;判断语句⭐单层if&#x1f388;示例 ⭐…

【python】制作一个串口工具(下)!

上一章节我们说了UI界面的设计&#xff0c;这一节来说下怎样实现其功能。 一.实例演示 1.创建一个.py文件&#xff0c;以下代码用来实现获取所有的串口信息&#xff1a; import serial import serial.tools.list_portsfrom PyQt5.QtWidgets import QComboBoxclass My_ComBoBo…

signed char 与 unsigned char 的取值范围

&#x1f517; 《C语言趣味教程》&#x1f448; 猛戳订阅&#xff01;&#xff01;&#xff01; 【C语言趣味教程】(2) 整数类型 | 数据类型的概念 | 原码反码与补码 | 有符号型和无符类型 | 研究 signed char 与 unsigned char 的取值范围 ​—— 热门专栏《维生素C语言》的重…