注解
本文将介绍 Easy-Es 注解包相关类详解(更多详细描述可点击查看源码注释)
# @EsMapperScan (opens new window)
描述:mapper扫描注解,功能与MP的@MapperScan一致
使用位置:Springboot启动类
@EsMapperScan("cn.easy-es-mapper")
public class Application{
// 省略其它...
}
2
3
4
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 是 | "" | 自定义mapper所在包全路径 |
温馨提示
由于EE和MP对Mapper的扫描都是采用Springboot的doScan,而且两套系统互相独立,所以在扫描的时候没有办法互相隔离,因此如果您的项目同时有用到EE和MP,您需要将EE的Mapper和MP的Mapper放在不同的包下,否则项目将无法正常启动。
# @Settings (opens new window)
描述:索引Settings信息注解,可设置ES索引中的Settings信息
使用位置:实体类
@Settings(shardsNum = 3, replicasNum = 2, settingsProvider = MySettingsProvider.class)
public class Document {
// 省略其它字段
}
2
3
4
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
shardsNum | Int | 否 | 1 | 索引分片数,默认值为1 |
replicasNum | Int | 否 | 1 | 索引副本数,默认值为1 |
maxResultWindow | Int | 否 | 10000 | 默认最大返回数 |
refreshInterval | String | 否 | "" | 索引的刷新间隔 es默认值为1s ms:表示毫秒 s:表示秒 m:表示分钟 |
settingsProvider | Class | 否 | DefaultSettingsProvider.class | 自定义settings提供类 默认为DefaultSettingsProvider空实现 如需自定义,可继承此类并覆写getSettings方法 将settings信息以Map返回 |
温馨提示
- maxResultWindow:默认最大返回数,默认值为10000,超过此值推荐使用searchAfter或滚动查询等方式,性能更好,详见拓展功能章节. 当此值调整至大于1W后,需要更新索引并同步开启配置文件中的enable-track-total-hits=true方可生效
- settingsProvider:自定义settings提供类,当小部分场景下,框架内置的这些参数不足以满足您对索引Settings的设置时,您可以自定义类并继承DefaultSettingsProvider,覆写其中的getSettings方法,将您自定义的settings信息以Map返回,通过此方式可以支持所有ES能够支持的Settings
# @IndexName (opens new window)
描述:索引名注解,标识实体类对应的索引 对应MP的@TableName注解,在v0.9.40之前此注解为@TableName.
使用位置:实体类
@IndexName
public class Document {
// 省略其它字段
}
2
3
4
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 索引名,可简单理解为MySQL表名 |
aliasName | String | 否 | "" | 索引别名 |
keepGlobalPrefix | boolean | 否 | false | 是否保持使用全局的 tablePrefix 的值,与MP用法一致 |
refreshPolicy | Enum | 否 | NONE | 索引数据刷新策略,默认为不刷新,其取值参考RefreshPolicy枚举类,一共有3种刷新策略 |
动态索引名称支持 如果你的索引名称是不固定的,我们提供了两种方式可修改CRUD时的索引名称
- 调用mapper.setCurrentActiveIndex(String indexName)方法,此处的mapper为你自定义的mapper,如documentMapper,通过此API修改索引名称后,全局生效.
- 在对应的参数中指定当前操作作用的索引,例如 wrapper.index(String indexName),通过此API修改索引名称后,仅作用于该wrapper对应的操作,粒度最细.
温馨提示
- 当您想直接把类名当作索引名,且并不需要对索引进行其它配置时,可省略此注解
- 通过注解指定的索引名称优先级最高,指定了注解索引,则全局配置和自动生成索引不生效,采用注解中指定的索引名称. 优先级排序: 注解索引>全局配置索引前缀>自动生成
- keepGlobalPrefix选项,(0.9.4+版本才支持)默认值为false,是否保持使用全局的 indexPrefix 的值:
- 既配置了全局tablePrefix,@TableName注解又指定了value值时,此注解选项才会生效,如果其值为true,则框架最终使用的索引名称为:全局indexPrefix+此注解的value,例如:dev_document
- 此注解选项用法和MP中保持一致.
- RefreshPolicy 数据刷新策略
- None 不刷新,es默认的策略,此策略下数据变更后有一定延迟才会生效,但写入性能最好,通常情况下使用此默认策略即可
- IMMEDIATE 立即刷新,适用于对数据延迟敏感的业务场景,但消耗的系统资源最大
- WAIT_UNTIL 请求提交数据后,等待数据完成刷新(约1s),再结束请求 性能损耗适中 属于折中方案
# @IndexId (opens new window)
- 描述:ES主键注解
- 使用位置:实体类中被作为ES主键的字段, 对应MP的@TableId注解
public class Document {
@IndexId
private String id;
// 省略其它字段
}
2
3
4
5
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
type | Enum | 否 | IdType.NONE | 指定主键类型 |
温馨提示
- 当您字段命名为id且类型为String时,且不需要采用UUID及自定义ID类型时,可省略此注解
- 由于es对id的默认名称做了处理(下划线+id):_id,所以EE已为您屏蔽这步操作,您无需在注解中指定,框架也会自动帮您完成映射.
- Id的生成类型支持以下几种:
- IdType.NONE: 由ES自动生成,是默认缺省时的配置,无需您额外配置 推荐
- IdType.UUID: 系统生成UUID,然后插入ES (不推荐)
- IdType.CUSTOMIZE: 由用户自定义,用户自己对id值进行set,如果用户指定的id在es中不存在,则在insert时就会新增一条记录,如果用户指定的id在es中已存在记录,则自动更新该id对应的记录.
优先级: 注解配置的Id生成策略>全局配置的Id生成策略
# @IndexField (opens new window)
- 描述:ES字段注解, 对应MP的@TableField注解
- 使用位置:实体类中被作为ES索引字段的字段
- 使用场景举例:
- 实体类中的字段并非ES中实际的字段,比如把实体类直接当DTO用了,加了一些ES中并不存在的无关字段,此时可以标记此字段,以便让EE框架跳过此字段,对此字段不处理.
- 字段的更新策略,比如在调用更新接口时,实体类的字段非Null或者非空字符串时才更新,此时可以加字段注解,对指定字段标记更新策略.
- 需要对类型为text或keyword_tex字段聚合时,可指定其fieldData=true,否则es会报错.
- 对指定字段进行自定义命名,比如该字段在es中叫wu-la,但在实体model中叫ula,此时可以在value中指定value="wu-la".
- 在自动托管索引模式下,可指定索引分词器及索引字段类型.
- 在自动托管索引模式下,可指定索引中日期的format格式.
- 可指定创建索引时,自动对指定字段添加忽略大小写的配置.
- 可指定稠密向量类型,支持向量检索.
- ...
使用示例:
public class Document {
// 此处省略其它字段...
// 场景一:标记es中不存在的字段
@IndexField(exist = false)
private String notExistsField;
// 场景二:更新时,此字段非空字符串才会被更新
@IndexField(strategy = FieldStrategy.NOT_EMPTY)
private String creator;
// 场景三: 指定fieldData
@IndexField(fieldType = FieldType.TEXT, fieldData = true)
private String filedData;
// 场景四:自定义字段名
@IndexField("wu-la")
private String ula;
// 场景五:支持日期字段在es索引中的format类型
@IndexField(fieldType = FieldType.DATE, dateFormat = "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis")
private String gmtCreate;
// 场景六:支持指定字段在es索引中的分词器类型
@IndexField(fieldType = FieldType.TEXT, analyzer = Analyzer.IK_SMART, searchAnalyzer = Analyzer.IK_MAX_WORD)
private String content;
// 场景七:支持指定字段在es的索引中忽略大小写,以便在term查询时不区分大小写,仅对keyword类型字段生效,es的规则,并非框架限制.
@IndexField(fieldType = FieldType.KEYWORD, ignoreCase = true)
private String caseTest;
// 场景八:支持稠密向量类型 稠密向量类型,dims必须同时指定,非负 最大为2048
@IndexField(fieldType = FieldType.DENSE_VECTOR, dims = 3)
private double[] vector;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 字段名 |
exist | boolean | 否 | true | 字段是否存在 |
fieldType | Enum | 否 | FieldType.NONE | 字段在es索引中的类型 |
fieldData | boolean | 否 | false | text类型字段是否支持聚合 |
analyzer | String | 否 | Analyzer.NONE | 索引文档时用的分词器 |
searchAnalyzer | String | 否 | Analyzer.NONE | 查询分词器 |
strategy | Enum | 否 | FieldStrategy.DEFAULT | 字段验证策略 |
dateFormat | String | 否 | "" | es索引中的日期格式,如yyyy-MM-dd |
nestedClass | Class | 否 | DefaultNestedClass.class | 嵌套类 |
parentName | String | 否 | "" | 父子文档-父名称 |
childName | String | 否 | "" | 父子文档-子名称 |
joinFieldClass | Class | 否 | JoinField.class | 父子文档-父子类型关系字段类 |
ignoreCase | boolean | 否 | false | keyword类型字段是否忽略大小写 |
ignoreAbove | int | 否 | 256 | 字符串将被索引或存储的最大长度 |
scalingFactor | int | 否 | 100 | 用于指定浮点数字段的缩放因子,scaled_float类型字段必须指定此参数,否则es创建索引报错 |
denseVector | String | 否 | "" | 稠密向量类型,可用于向量检索 |
dims | int | 否 | -1 | 向量的维度大小,不能超过2048 且非负 |
温馨提示
- 更新策略一共有3种:
- NOT_NULL: 非Null判断,字段值为非Null时,才会被更新
- NOT_EMPTY: 非空判断,字段值为非空字符串时才会被更新
- IGNORE: 忽略判断,无论字段值为什么,都会被更新
- 针对BigDecimal类型字段,其scalingFactor若用户未指定,则系统默认值为100
其中场景四和场景五仅在索引自动托管模式下生效,如果开启了手动处理索引模式,则需要用户通过手动调用我提供的API传入相应的分词器及日期格式化参数进行索引的创建/更新.
# @MultiIndexField (opens new window)
- 描述:多字段注解
- 使用位置:实体类中单个字段期望用多种分词器或多种字段类型的字段上
- 使用场景举例:比如一个字段既想要用中文分词器查询,又想要用拼音分词器查询
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
mainIndexField | @IndexField | 是 | - | 主字段必须指定,用法可以参考上面的@IndexField |
InnerIndexField | @InnerIndexField[] | 否 | {} | 内部字段,可以为空数组,当内部字段不指定时,则此注解降级为@IndexField,与@IndexField注解效果一致 |
# @InnerIndexField (opens new window)
- 描述:内部字段注解
- 使用位置:@MultiIndexField内部
- 使用场景举例:比如一个字段既想要用中文分词器查询,又想要用拼音分词器查询,可以在@MultiIndexField中指定
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
suffix | String | 是 | - | 内部字段后缀 |
fieldType | FieldType | 是 | - | 内部字段的字段类型,此枚举与@IndexField中的FieldType是同一个,用法可以直接参考 |
analyzer | String | 否 | - | 索引分词器,与@IndexField中的Analyzer是同一个,用法可直接参考 |
searchAnalyzer | String | 否 | - | 查询分词器,与@IndexField中的Analyzer是同一个,用法可直接参考 |
ignoreAbove | int | 否 | 256 | 内部字段,字符串将被索引或存储的最大长度 |
使用示例:
public class Document {
/**
* 复合字段,此注解和SpringData中的MultiField用法类似 适用于对同一个字段通过多种分词器检索的场景
*/
@MultiIndexField(mainIndexField = @IndexField(fieldType = FieldType.KEYWORD),
otherIndexFields = {@InnerIndexField(suffix = "zh", fieldType = FieldType.TEXT, analyzer = Analyzer.IK_SMART),
@InnerIndexField(suffix = "pinyin", fieldType = FieldType.TEXT, analyzer = Analyzer.PINYIN)})
private String multiField;
}
2
3
4
5
6
7
8
9
查询示例:
@Test
public void testMultiFieldSelect() {
// 药品 中文名叫葡萄糖酸钙口服溶液 英文名叫 Calcium Gluconate 汉语拼音为 putaotangsuangaikoufurongye
// 用户可以通过模糊检索,例如输入 Calcium 或 葡萄糖 或 putaotang时对应药品均可以被检索到
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
wrapper.match("english", "Calcium")
.or()
.match("multi_field.zh", "葡萄糖")
.or()
.match("multi_field.pinyin", "putaotang");
List<Document> documents = documentMapper.selectList(wrapper);
System.out.println(documents);
}
2
3
4
5
6
7
8
9
10
11
12
13
上述使用案例中,开启了驼峰自动转下划线,因此字段名为"multi_field",实际上在查询中用户只需要用"字段名.suffix"组合,即可确定当前启用哪个内部字段,当查询主字段时,则无需指定suffix,直接字段名即可.
# @HighLight (opens new window)
- 描述:高亮注解
- 使用位置:实体类中需要高亮的被查询字段
- 使用场景举例:比如输入关键词"老汉"进行查询,期望内容中包含"老汉"的部分被展示为红色或加粗
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
mappingField | String | 否 | "" | 高亮内容映射字段的名称,比如我想把高亮内容"老汉"赋值到字段pushCar上,就可以指定此属性值为pushCar |
fragmentSize | int | 否 | 100 | 高亮字段截取长度,默认为100 |
numberOfFragments | int | 否 | -1 | 搜索返回的高亮片段数量,默认全部返回 |
preTag | String | 否 | < em > | 高亮标签,高亮内容将处于preTag之后 |
postTag | String | 否 | < /em > | 高亮标签,高亮内容将处于postTag之前 |
highLightType | HighLightTypeEnum | 否 | UNIFIED | 高亮类型 |
requireFieldMatch | boolean | 否 | true | 高亮内容是否需要与查询字段匹配,默认值为true,当为否时,命中内容中非查询字段包含高亮内容时也会被高亮 |
# @Score (opens new window)
- 描述:得分注解
- 使用位置:实体类中被作为ES查询得分返回的字段
- 使用场景举例:比如需要知道本次匹配查询得分有多少时,可以在实体类中添加一个类型为Float/float的字段,并在该字段上添加@Score注解,在后续查询中,若es有返回当次查询的得分,则此得分会自动映射至此字段上
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
decimalPlaces | int | 否 | 0 | 得分保留小数位,默认不处理,保持es返回的得分值 |
# @Distance (opens new window)
- 描述:距离注解
- 使用位置:实体类中被作为ES地理位置排序距离值的返回字段
- 使用场景举例:比如需要知道按距离由近及远查询后的数据,实际距离某一坐标有多远,可以在实体类中添加一个类型为Double/double的字段,并在该字段上添加@Distance注解,在后续查询中,若es有返回距离,则此距离会自动映射至此字段上
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
decimalPlaces | int | 否 | 0 | 距离保留小数位,默认不处理,保持es返回的距离值 |
# @EsDS (opens new window)
- 描述:多数据源注解
- 使用位置:继承自BaseEsMapper的自定义的Mapper
- 使用场景举例:比如有多个ES,想让不同的Mapper连不同的ES,用法和Mybatis-Plus中的@DS是一样的
- 更多使用介绍可前往核心功能 -> 多数据源支持 章节进行学习
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 数据源名称,与配置文件中指定的一致 |
# @Join (opens new window)
描述:Join父子类型注解,用于父子类型索引关系表达
使用位置:父子类型根节点Root类
/**
* Document根文档有子文档Author(作者)和Comment(评论),其中Author还有个子文档Contact(联系方式)
* Join父子类型结构如下所示
* Document
* / \
* Comment Author
* \
* Contact
* 上述结构可用@Join注解和@Node注解来表达,可参考下面案例
**/
@Join(nodes = {@Node(parentClass = Document.class, childClasses = {Author.class, Comment.class}), @Node(parentClass = Author.class, childClasses = Contact.class)})
public class Document {
// 省略其它无关字段
}
2
3
4
5
6
7
8
9
10
11
12
13
14
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
joinField | String | 否 | "" | 索引中的join字段名称 默认为joinField(推荐) |
rootAlias | String | 否 | "" | 根节点别名 不指定则默认使用加了当前注解的根类的名称小写作为根节点别名(推荐) |
nodes | Annotation[] | 是 | "" | 非根节点列表 |
eagerGlobalOrdinals | boolean | 否 | true | 是否创建全局序数,默认创建,可提升查询性能 |
温馨提示
更多关于此注解的使用可以参考Join父子类型章节文档
# @Node (opens new window)
描述:Join父子类型注解,用于父子类型索引关系表达
使用位置:父子类型根节点Root类
/**
* Document根文档有子文档Author(作者)和Comment(评论),其中Author还有个子文档Contact(联系方式)
* Join父子类型结构如下所示
* Document
* / \
* Comment Author
* \
* Contact
* 上述结构可用@Join注解和@Node注解来表达,可参考下面案例
**/
@Join(nodes = {@Node(parentClass = Document.class, childClasses = {Author.class, Comment.class}), @Node(parentClass = Author.class, childClasses = Contact.class)})
public class Document {
// 省略其它无关字段
}
2
3
4
5
6
7
8
9
10
11
12
13
14
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
parentAlias | String | 否 | "" | 父文档别名 非必填,不指定时默认值为parentClass类名小写(推荐) |
parentClass | Class | 是 | - | 父文档实体类,必填项 |
childAliases | String | 否 | "" | 子文档别名列表,不指定则为子文档类名小写列表(推荐) 若要自定义必须与childClasses数量和顺序一致 |
childClasses | Class | 是 | - | 子文档实体类列表,必填项 |
温馨提示
更多关于此注解的使用可以参考Join父子类型章节文档
# 其它注解
除了上面这几个高频注解,项目中偶尔还会用到一些其它注解,比如比如拦截器注解@Intercepts等注解,我们会在后面具体的章节详细介绍,此处仅列出几个必须掌握的注解,其它注解按需学习即可。