Routing values
-
RoutingResolver:实现一个自定义路由解析器,提供动态路由值计算。
当 Elasticsearch 将文档存储在具有多个分片的索引中时,它根据文档的 id 确定要使用的分片。有时有必要预定义多个文档应在同一分片上编制索引(连接类型,针对相关数据进行更快的搜索)。对此,Elasticsearch 提供了定义路由的可能性,该值应用来代替 id 计算分片。
When Elasticsearch stores a document in an index that has multiple shards, it determines the shard to you use based on the id of the document. Sometimes it is necessary to predefine that multiple documents should be indexed on the same shard (join-types, faster search for related data). For this Elasticsearch offers the possibility to define a routing, which is the value that should be used to calculate the shard from instead of the id.
Spring Data Elasticsearch 通过以下途径支持路由定义,用于存储和检索数据:
Spring Data Elasticsearch supports routing definitions on storing and retrieving data in the following ways:
Routing on join-types
当使用联接类型时(见 Join-Type implementation),Spring 数据 Elasticsearch 将自动使用实体 JoinField
属性的 parent
属性作为路由的值。
When using join-types (see Join-Type implementation), Spring Data Elasticsearch will automatically use the parent
property of the entity’s JoinField
property as the value for the routing.
对于所有母子关系只有一级的用例来说,这是正确的。如果它更深,例如像上面的从 vote → answer → question 的示例中的子-母-祖父母关系,那么需要通过使用下一节中描述的技术显式指定路由(vote 需使用 question.id 作为路由值)。
This is correct for all the use-cases where the parent-child relationship has just one level. If it is deeper, like a child-parent-grandparent relationship - like in the above example from vote → answer → question - then the routing needs to explicitly specified by using the techniques described in the next section (the vote needs the question.id as routing value).
Custom routing values
为了为实体定义自定义路由,Spring Data Elasticsearch 提供了一个 @Routing
注释(重新使用上面的 Statement
类):
To define a custom routing for an entity, Spring Data Elasticsearch provides a @Routing
annotation (reusing the Statement
class from above):
@Document(indexName = "statements")
@Routing("routing") 1
public class Statement {
@Id
private String id;
@Field(type = FieldType.Text)
private String text;
@JoinTypeRelations(
relations =
{
@JoinTypeRelation(parent = "question", children = {"answer", "comment"}),
@JoinTypeRelation(parent = "answer", children = "vote")
}
)
private JoinField<String> relation;
@Nullable
@Field(type = FieldType.Keyword)
private String routing; 2
// getter/setter...
}
1 | This defines "routing" as routing specification |
2 | a property with the name routing |
如果注释的 routing
规范是纯字符串而不是 SpEL 表达式,那么它将被解释为实体属性的名称,在本例中是 routing 属性。然后,此属性的值将用作所有使用该实体的请求的路由值。
If the routing
specification of the annotation is a plain string and not a SpEL expression, it is interpreted as the name of a property of the entity, in the example it’s the routing property.
The value of this property will then be used as the routing value for all requests that use the entity.
还可以在 @Document
注释中使用 SpEL 表达式,如下所示:
It is also possible to us a SpEL expression in the @Document
annotation like this:
@Document(indexName = "statements")
@Routing("@myBean.getRouting(#entity)")
public class Statement{
// all the needed stuff
}
在这种情况下,用户需要提供具有名为 myBean 的 Bean,它具有方法 String getRouting(Object)
。要在 SpEL 表达式中引用实体 "#entity",且返回值必须为 null
或字符串形式的路由值。
In this case the user needs to provide a bean with the name myBean that has a method String getRouting(Object)
. To reference the entity "#entity" must be used in the SpEL expression, and the return value must be null
or the routing value as a String.
如果普通的属性名称和 SpEL 表达式还不能自定义路由定义,可以定义提供 RoutingResolver
接口的实现。然后可以将其设置在 ElasticOperations
实例上:
If plain property’s names and SpEL expressions are not enough to customize the routing definitions, it is possible to define provide an implementation of the RoutingResolver
interface. This can then be set on the ElasticOperations
instance:
RoutingResolver resolver = ...;
ElasticsearchOperations customOperations= operations.withRouting(resolver);
withRouting()
函数返回具有自定义路由设置的原始 ElasticsearchOperations
实例的一个副本。
The withRouting()
functions return a copy of the original ElasticsearchOperations
instance with the customized routing set.
当在 Elasticsearch 中存储实体时在实体上定义一个路由,执行 get 或 delete 操作时必须提供相同的值。对于那些不使用实体的方法(如 get(ID)
或 delete(ID)
),可以使用 ElasticsearchOperations.withRouting(RoutingResolver)
方法,如下所示:
When a routing has been defined on an entity when it is stored in Elasticsearch, the same value must be provided when doing a get or delete operation. For methods that do not use an entity - like get(ID)
or delete(ID)
- the ElasticsearchOperations.withRouting(RoutingResolver)
method can be used like this:
String id = "someId";
String routing = "theRoutingValue";
// get an entity
Statement s = operations
.withRouting(RoutingResolver.just(routing)) 1
.get(id, Statement.class);
// delete an entity
operations.withRouting(RoutingResolver.just(routing)).delete(id);
1 | RoutingResolver.just(s) returns a resolver that will just return the given String. |