此版本仍在开发中,尚未视为稳定版。如需最新稳定版本,请使用 Spring Data Elasticsearch 6.0.4spring-doc.cadn.net.cn

路由值

当 Elasticsearch 将文档存储到具有多个分片的索引中时,它会根据文档的 id 确定要使用的分片。 有时需要预先定义多个文档应被索引到同一个分片上(例如用于关联类型、加速相关数据的搜索)。 为此,Elasticsearch 提供了定义路由的功能,该路由值是用于计算分片的依据,替代默认的 idspring-doc.cadn.net.cn

Spring Data Elasticsearch 支持通过以下方式在存储和检索数据时定义路由:spring-doc.cadn.net.cn

基于连接类型的路由

当使用连接类型时(请参阅 连接类型实现),Spring Data Elasticsearch 将自动使用实体的 JoinField 属性中的 parent 属性值作为路由值。spring-doc.cadn.net.cn

这对于所有父子关系仅有一层的使用场景都是正确的。 如果层级更深,例如子 - 父 - 祖父的关系(如上述从 voteanswerquestion 的示例),则需要使用下一节中描述的技术显式指定路由(即 vote 需要将 question.id 作为路由值)。spring-doc.cadn.net.cn

自定义路由值

要为实体定义自定义路由,Spring Data Elasticsearch 提供了一个 @Routing 注解(复用上面的 Statement 类):spring-doc.cadn.net.cn

@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 属性。 该属性的值将随后用作所有使用该实体的请求的路由值。spring-doc.cadn.net.cn

也可以在 @Document 注解中使用 SpEL 表达式,如下所示:spring-doc.cadn.net.cn

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

在这种情况下,用户需要提供一个名为 myBean 的 Bean,该 Bean 包含一个名为 String getRouting(Object) 的方法。在 SpEL 表达式中必须使用 "#entity" 来引用实体,且返回值必须为 null 或以字符串形式表示的路由值。spring-doc.cadn.net.cn

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

RoutingResolver resolver = ...;

ElasticsearchOperations customOperations= operations.withRouting(resolver);

withRouting() 函数返回原始 ElasticsearchOperations 实例的副本,并设置了自定义路由。spring-doc.cadn.net.cn

当在实体上定义了路由并将其存储到 Elasticsearch 时,在执行 getdelete 操作时必须提供相同的值。对于不使用实体的方法(例如 get(ID)delete(ID)),可以按如下方式使用 ElasticsearchOperations.withRouting(RoutingResolver) 方法:spring-doc.cadn.net.cn

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) 返回一个解析器,该解析器将直接返回给定的字符串。