索引定义
搜索的索引是通过 Java 接口定义的,接口中描述哪些实体以及哪些属性需要建立索引。需要为每一个启用全文搜索的实体创建此类接口。
索引定义接口
索引定义的 Java 接口需要满足下列条件:
-
命名无限制。
-
需要使用
@JmixEntitySearchIndex
注解。 -
注解必须有
entity
参数,定义此接口服务的实体。每个可搜索的实体对应一个索引定义接口。
@JmixEntitySearchIndex(entity = Order.class)
public interface OrderIndexDefinition {
}
实体属性索引通过接口的方法定义。方法需要满足下列条件:
-
必须返回
void
。 -
命名无限制。
-
无参数。
-
无具体实现。
-
需要使用
@AutoMappedField
注解。
@JmixEntitySearchIndex(entity = Order.class)
public interface OrderIndexDefinition {
@AutoMappedField(includeProperties =
{"number", "product", "customer.status", "customer.lastName"})
void orderMapping();
}
AutoMappedField 注解
@AutoMappedField
注解支持将实体属性根据其类型映射为 ES 索引(参见 下文)。该注解有下列参数:
-
includeProperties
- 应该建立索引的实体属性列表。支持使用点标记指定关联实体的属性。默认不包含任何属性,即不建立任何属性的索引。 -
excludeProperties
- 不需要建立索引的实体属性列表。支持使用点标记指定关联实体的属性。默认不包含任何属性。 -
analyzer
- ES 中定义的分析器(Analyzer)名称,用在索引字段映射中。如果未指定,则使用 ES 的 默认分析器。 -
indexFileContent
- 定义是否对文件属性的文件内容建立索引。默认true
。
includeProperties
和 excludeProperties
都支持 *
通配符。该通配符将转换为相应级别的本地属性:
-
*
- 索引实体的本地属性。 -
refField.*
-refField
属性指定的关联实体的本地属性。
通配符不覆盖反向引用属性和实体 特性 属性:version
、createdBy
等。
仅当 includeProperties
包含通配符时,使用 excludeProperties
比较方便,用于限制属性范围。示例:
@AutoMappedField(
includeProperties = {"*", "customer.*"},
excludeProperties = {"number", "customer.firstName"})
void orderCustomerMapping();
分析器以不同的方式转换输入文本值,包括对某些语言词法的解析。指定的分析器用于索引和搜索步骤。
@JmixEntitySearchIndex(entity = Customer.class)
public interface CustomerIndexDefinition {
@AutoMappedField(
includeProperties = {"firstName", "lastName"},
analyzer = "russian")
void customerMapping();
}
可以在单个方法上设置多个映射注解,也可以分组后在多个方法之间拆分。以下示例都表示同一个定义:
@JmixEntitySearchIndex(entity = Order.class)
public interface OrderIndexDefinition {
@AutoMappedField(includeProperties =
{"number", "product", "customer.status", "customer.lastName"})
void orderMapping();
}
@JmixEntitySearchIndex(entity = Order.class)
public interface OrderIndexDefinition {
@AutoMappedField(includeProperties = {"number", "product"})
@AutoMappedField(includeProperties = {"customer.status", "customer.lastName"})
void orderMapping();
}
@JmixEntitySearchIndex(entity = Order.class)
public interface OrderIndexDefinition {
@AutoMappedField(includeProperties = {"number", "product"})
void orderMapping();
@AutoMappedField(includeProperties = {"customer.status", "customer.lastName"})
void customerMapping();
}
自动映射
@AutoMappedField
注解的自动映射支持下列类型的实体属性:
通配符能覆盖所有这些属性。
文本类型
这是 String
类型的属性,也是最常见的情况,属性值用作索引值。ES 中的索引字段类似这样:
"textualFieldName": "value"
如果有多个值:
"textualFieldName": ["value1", "value2"]
引用实体
这是关联实体的引用。只有关联实体的实例名用作索引值,不包含关联实体的任何内部属性。如需对关联实体的内部属性建立索引,需要显式添加 refProperty.nestedProperty
或 refProperty.*
。
ES 中的索引字段类似这样:
"refFieldName": {
"_instance_name": "instanceNameValue"
}
如果有多个值:
"refFieldName": {
"_instance_name": ["instanceNameValue1", "instanceNameValue2"]
}
文件类型
这是 FileRef
类型的属性,引用 文件存储 中的文件。文件名和文件内容默认都会用作索引值。如果仅需对文件名建立索引,需要设置 @AutoMappedField
的 indexFileContent
参数为 false
:
@AutoMappedField(
includeProperties = {"*"},
indexFileContent = false)
void fileMapping();
ES 中的索引字段类似这样:
"fileRefField": {
"_file_name" : "File name",
"_content" : "File content if enabled"
}
如果有多个值:
"fileRefField": [
{
"_file_name" : "File name 1",
"_content" : "File content 1"
},
{
"_file_name" : "File name 2",
"_content" : "File content 2"
}
]
枚举类型
ES 中的索引字段类似这样:
"enumFieldName": ["enValue", "ruValue"]
如果有多个值,则会展示所有值的所有语言本地化值:
"enumFieldName": ["enValue1", "ruValue1", "enValue2", "ruValue2"]
嵌入实体
这是内部 JPA 实体的引用。包含一个嵌入实体属性与包含该实体所有内部属性("someEmbeddedProperty" = "someEmbeddedProperty.*")一致。索引值根据内部属性的不同类型构建,会忽略不支持的类型。
假设一个根实体的 customer
属性关联至内部的 Customer
实体(具有 firstName
和 lastName
属性)。如果在映射中包含了 customer
属性,则会导致间接包含 customer.firstName
和 customer.lastName
属性。
内部属性和集合
内部嵌套属性可用点标记指定:refProperty.nestedRefProperty.targetDataProperty
。
集合属性也支持包含不同级别的内部集合属性。此时索引会存储最低一级属性的全部值。例如,collectionOfReferences.nestedCollectionOfAnotherReferences.name
保存如下:
"collectionOfEntityA": {
"nestedCollectionOfEntityB": {
"name": ["value1", ..., "valueN"]
}
}
数组包含根实体中全部 EntityA
实例的全部 EntityB
实例的 name
属性值。
编程式映射
除了使用注解之外,还可以通过编程的方式构建映射定义。
需要在索引定义接口中创建满足下列条件的方法:
-
需要是 default 方法。
-
命名无限制。
-
为了自定义配置,可以使用 Spring bean 作为参数。
-
需要返回
MappingDefinition
类型。 -
需要使用
@ManualMappingDefinition
注解。
方法体中,使用 MappingDefinition.builder()
创建映射定义。
@JmixEntitySearchIndex(entity = Customer.class)
public interface CustomerIndexDefinition {
@ManualMappingDefinition (1)
default MappingDefinition mapping(FilePropertyValueExtractor filePropertyValueExtractor) { (2)
return MappingDefinition.builder()
.addElement(
MappingDefinitionElement.builder()
.includeProperties("*") (3)
.excludeProperties("hobby", "maritalStatus") (4)
.withFieldMappingStrategyClass(AutoMappingStrategy.class) (5)
.withPropertyValueExtractor(filePropertyValueExtractor) (6)
.build()
)
.build();
}
}
1 | @ManualMappingDefinition 注解标记的方法使用了手动创建映射定义。 |
2 | 为了自定义映射配置,可以传入 Spring bean 作为参数。 |
3 | 需要建立索引的属性列表。这里使用 * 通配符包含 Customer 实体的所有本地属性。 |
4 | 不需要建立索引的属性列表。 |
5 | 需要用 FieldMappingStrategy 的实现类做属性映射。映射策略也可以定义为类的实例,需要用 withFieldMappingStrategy() 方法设置,参数为映射策略的实例。 |
6 | 显式指定属性值解析器。例如,FilePropertyValueExtractor 可用于处理 FileRef 类型的属性。 |
只能有一个编程式映射的方法。如果存在此方法,则会忽略所有的映射注解。 |