Routing values

  • RoutingResolver:实现一个自定义路由解析器,提供动态路由值计算。

当 Elasticsearch 将文档存储在具有多个分片的索引中时,它根据文档的 id 确定要使用的分片。有时有必要预定义多个文档应在同一分片上编制索引(连接类型,针对相关数据进行更快的搜索)。对此,Elasticsearch 提供了定义路由的可能性,该值应用来代替 id 计算分片。 Spring Data Elasticsearch 通过以下途径支持路由定义,用于存储和检索数据:

Routing on join-types

当使用联接类型时(见 Join-Type implementation),Spring 数据 Elasticsearch 将自动使用实体 JoinField 属性的 parent 属性作为路由的值。

对于所有母子关系只有一级的用例来说,这是正确的。如果它更深,例如像上面的从 voteanswerquestion 的示例中的子-母-祖父母关系,那么需要通过使用下一节中描述的技术显式指定路由(vote 需使用 question.id 作为路由值)。

Custom routing values

为了为实体定义自定义路由,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...
}
1 这将 "routing" 定义为路由规范
2 名称为 routing 的属性

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

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

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

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

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

RoutingResolver resolver = ...;

ElasticsearchOperations customOperations= operations.withRouting(resolver);

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);
1 RoutingResolver.just(s) 返回将仅返回给定 String 的解析器。