Cassandra-specific Query Methods

本章解释了特定于 Cassandra 的查询方法。此文档使用命令式类型。通过使用响应式返回类型,相同的语义也适用于响应式存储库。

在存储库上通常触发的多数数据访问操作最终会针对 Apache Cassandra 数据库执行查询。此类查询的定义只是在存储库接口上声明一个方法。以下示例显示多个此类方法声明:

Example 1. PersonRepository with query methods
Imperative
interface PersonRepository extends CrudRepository<Person, String> {

    List<Person> findByLastname(String lastname);                           1

    Slice<Person> findByFirstname(String firstname, Pageable pageRequest);  2

    Window<Person> findByFirstname(String firstname, CassandraScrollPosition pos, Limit limit);  3

    List<Person> findByFirstname(String firstname, QueryOptions opts);      4

    List<Person> findByFirstname(String firstname, Sort sort);              5

    List<Person> findByFirstname(String firstname, Limit limit);            6

    Person findByShippingAddress(Address address);                          7

    Person findFirstByShippingAddress(Address address);                     8

    Stream<Person> findAllBy();                                             9

    @AllowFiltering
    List<Person> findAllByAge(int age);                                     10
}
1 16. 此方法显示了给定`lastname`的所有人的查询。此查询是由分析方法名称派生的,该方法名称用于确定约束,可以将这些约束与`And`连接起来。因此,方法名称生成一个查询表达式`SELECT * FROM person WHERE lastname = 'lastname'`。
2 17. 对查询应用分页。你可以用`Pageable`参数为你的方法签名配备一个,并让方法返回一个`Slice`实例,我们便可以按要求自动分页查询。
3 18. 对查询应用滚动。滚动将Cassandra的`PagingState`包装到`CassandraScrollPosition`中并允许动态限制。你也可以对静态限制使用`findTop…`。
4 19. 传入`QueryOptions`对象会在执行前对结果查询应用查询选项。
5 应用动态排序到查询。您可以在您的方法签名中添加 Sort 参数,Spring Data 会自动将排序应用到查询。
6 应用动态结果限制到查询。可以使用 SELECT … LIMIT 限制查询结果。
7 表明您可以根据非原始类型的属性使用 CustomConversions 中注册的 Converter 实例进行查询。如果找到多个匹配项,则抛出 IncorrectResultSizeDataAccessException
8 使用 First 关键字仅将查询限制到第一个结果。与前一个方法不同,此方法在找到多个匹配项时不会抛出异常。
9 使用 Java 8 Stream 在迭代流时读取和转换各个元素。
10 展示使用 @AllowFiltering 注释的查询方法,以允许服务器端过滤。
Reactive
interface ReactivePersonRepository extends ReactiveSortingRepository<Person, Long> {

  Flux<Person> findByFirstname(String firstname);                                1

  Flux<Person> findByFirstname(Publisher<String> firstname);                     2

  Mono<Person> findByFirstnameAndLastname(String firstname, String lastname);    3

  Mono<Person> findFirstByFirstname(String firstname);                           4

  @AllowFiltering
  Flux<Person> findByAge(int age);                                               5
}
11 针对具有既定 firstname 的所有人的查询。通过解析方法名称以获取约束来导出查询,这些约束可以与 AndOr 级联。因此,方法名称生成了 SELECT * FROM person WHERE firstname = :firstname 的查询表达式。
12 针对具有既定 firstname 的所有人的查询,一旦 firstname 从既定 Publisher 中发出。
13 查找给定条件的单个实体。对于非唯一结果,使用 IncorrectResultSizeDataAccessException 完成。
14 与前一个查询不同,即使查询产生更多结果行,也会始终发出第一个实体。
15 使用 @AllowFiltering 注释的查询方法,这允许服务器端过滤。

查询非主键属性需要二级索引。

下表显示了可以在查询方法中使用的关键字的简短示例:

Table 1. Supported keywords for query methods
Keyword Sample Logical result

After

findByBirthdateAfter(Date date)

birthdate > date

GreaterThan

findByAgeGreaterThan(int age)

age > age

GreaterThanEqual

findByAgeGreaterThanEqual(int age)

age >= age

Before

findByBirthdateBefore(Date date)

birthdate < date

LessThan

findByAgeLessThan(int age)

age < age

LessThanEqual

findByAgeLessThanEqual(int age)

age ⇐ age

Between

findByAgeBetween(int from, int to)findByAgeBetween(Range<Integer> range)

age > from AND age < to 和下/上界(> / >=< / ),根据 Range

In

findByAgeIn(Collection ages)

age IN (ages…​)

Like, StartingWith, EndingWith

findByFirstnameLike(String name)

firstname LIKE (name as like expression)

Containing on String

findByFirstnameContaining(String name)

firstname LIKE (name as like expression)

Containing on Collection

findByAddressesContaining(Address address)

addresses CONTAINING address

(No keyword)

findByFirstname(String name)

firstname = name

IsTrue, True

findByActiveIsTrue()

active = true

IsFalse, False

findByActiveIsFalse()

active = false

Repository Delete Queries

前表中的关键字可与 delete…By 结合使用,以创建删除匹配文档的查询。

  • Imperative

  • Reactive

interface PersonRepository extends Repository<Person, String> {

  void deleteWithoutResultByLastname(String lastname);

  boolean deleteByLastname(String lastname);
}
interface PersonRepository extends Repository<Person, String> {

  Mono<Void> deleteWithoutResultByLastname(String lastname);

  Mono<Boolean> deleteByLastname(String lastname);
}

删除查询返回查询是否已应用或使用 void 终止而不返回值。

Query Options

您可以通过传递 QueryOptions 对象为查询方法指定查询选项。这些选项应用于查询在实际查询执行之前。QueryOptions 被视为非查询参数,而不被视为查询参数值。查询选项适用于派生查询和字符串 @Query 存储库方法。

要静态设置一致性级别,请对查询方法使用 @Consistency 注释。每次执行查询时都会应用已声明的一致性级别。以下示例将一致性级别设置为 ConsistencyLevel.LOCAL_ONE

  • Imperative

  • Reactive

interface PersonRepository extends CrudRepository<Person, String> {

    @Consistency(ConsistencyLevel.LOCAL_ONE)
    List<Person> findByLastname(String lastname);

    List<Person> findByFirstname(String firstname, QueryOptions options);
}
interface PersonRepository extends ReactiveCrudRepository<Person, String> {

    @Consistency(ConsistencyLevel.LOCAL_ONE)
    Flux<Person> findByLastname(String lastname);

    Flux<Person> findByFirstname(String firstname, QueryOptions options);
}

DataStax Cassandra 文档包括 a good discussion of the available consistency levels

您可以通过配置 CQL API 实例上的以下参数来控制获取大小、一致性级别和重试策略的默认值: CqlTemplateAsyncCqlTemplateReactiveCqlTemplate。如果未设置特定查询选项,则应用默认值。