跳到主要内容

路由值

DeepSeek V3 中英对照 Routing values

当 Elasticsearch 在具有多个分片的索引中存储文档时,它会根据文档的 id 来确定要使用的分片。有时需要预先定义多个文档应存储在同一个分片上(例如连接类型或更快地搜索相关数据)。为此,Elasticsearch 提供了定义路由的可能性,路由是用于计算分片的值,而不是使用 id 来计算。

Spring Data Elasticsearch 支持在存储和检索数据时通过以下方式定义路由:

基于连接类型的路由

在使用连接类型(参见连接类型实现)时,Spring Data Elasticsearch 会自动将实体的 JoinField 属性的 parent 属性值用作路由的值。

这对于所有父子关系仅有一层的情况都是正确的。如果关系更深,比如子-父-祖父关系——就像上面例子中的 voteanswerquestion ——那么路由需要通过使用下一节中描述的技术来显式指定(vote 需要 question.id 作为路由值)。

自定义路由值

要为实体定义自定义路由,Spring Data Elasticsearch 提供了 @Routing 注解(重用上面的 Statement 类):

@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...
}
java
  • 这将 "路由" 定义为路由规范

  • 一个名为 routing 的属性

如果注解的 routing 规范是一个纯字符串而不是 SpEL 表达式,则它被解释为实体的某个属性的名称,在示例中它是 routing 属性。该属性的值将用作使用该实体的所有请求的路由值。

也可以在 @Document 注解中使用 SpEL 表达式,如下所示:

@Document(indexName = "statements")
@Routing("@myBean.getRouting(#entity)")
public class Statement{
// all the needed stuff
}
java

在这种情况下,用户需要提供一个名为 myBean 的 bean,该 bean 具有一个方法 String getRouting(Object)。在 SpEL 表达式中,必须使用实体 "#entity" 来引用实体,并且返回值必须为 null 或作为字符串的路由值。

如果普通的属性名称和 SpEL 表达式不足以自定义路由定义,可以提供一个 RoutingResolver 接口的实现。然后可以将其设置在 ElasticOperations 实例上:

RoutingResolver resolver = ...;

ElasticsearchOperations customOperations= operations.withRouting(resolver);
java

withRouting() 函数返回一个带有自定义路由设置的原始 ElasticsearchOperations 实例的副本。

当在 Elasticsearch 中存储实体时定义了路由,执行 getdelete 操作时必须提供相同的路由值。对于不使用实体的方法(如 get(ID)delete(ID)),可以使用 ElasticsearchOperations.withRouting(RoutingResolver) 方法,如下所示:

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);
java
  • RoutingResolver.just(s) 返回一个解析器,该解析器将直接返回给定的字符串。