11.3. 搜索


使用 Ickle 查询语言在 Library 和 Remote Client-Server 模式中创建关系和全文本查询。

要使用 API,首先获取 QueryFactory 到缓存,然后调用 .create () 方法,传递字符串以便在查询中使用。每个 QueryFactory 实例都绑定到与 Search 相同的 缓存 实例,但它是一个无状态和 thread-safe 对象,可用于并行创建多个查询。

例如:

// Remote Query, using protobuf
QueryFactory qf = org.infinispan.client.hotrod.Search.getQueryFactory(remoteCache);
Query q = qf.create("from sample_bank_account.Transaction where amount > 20");

// Embedded Query using Java Objects
QueryFactory qf = org.infinispan.query.Search.getQueryFactory(cache);
Query q = qf.create("from com.acme.Book where price > 20");

// Execute the query
QueryResult<Book> queryResult = q.execute();
注意

查询将始终以单个实体类型为目标,并在单个缓存的内容上评估。不支持对多个缓存运行查询,或创建以多个实体类型(连接)为目标的查询。

执行查询并获取结果非常简单,就像调用 Query 对象的 run () 方法一样简单。执行之后,在同一实例上调用 run () 将重新执行查询。

11.3.1. 分页

您可以使用 Query.maxResults (int maxResults) 限制返回的结果数量。这可与 Query.startOffset (long startOffset) 一起使用,来实现结果集的分页。

// sorted by year and match all books that have "clustering" in their title
// and return the third page of 10 results
Query<Book> query = queryFactory.create("FROM com.acme.Book WHERE title like '%clustering%' ORDER BY year").startOffset(20).maxResults(10)

11.3.2. Hits 的数量

QueryResult 对象具有 .hitCount () 方法,可以返回查询的结果总数,而不考虑任何分页参数。因为性能的原因,点击数仅适用于索引的查询。

11.3.3. 迭代

Query 对象具有 .iterator () 方法,可以完全获得结果。它返回一个在使用后必须关闭的 CloseableIterator 实例。

注意

远程查询的迭代支持当前有限,因为它在迭代前首先获取客户端的所有条目。

11.3.4. 使用 Named Query 参数

可以不必为每个执行构建一个新的 Query 对象,而是在查询中包含命名参数,这些参数可以在执行前使用实际值替换。这允许定义一次查询,并可以有效地执行多次。参数只能在操作器的右侧使用,并通过提供由 org.infinispan.query.dsl.Expression.param (String paramName) 方法生成的对象来创建查询时定义。定义参数后,可以通过调用 Query.setParameter (parameterName, value)Query.setParameters (parameterMap) 来设置参数,如以下示例所示。

QueryFactory queryFactory = Search.getQueryFactory(cache);
// Defining a query to search for various authors and publication years
Query<Book> query = queryFactory.create("SELECT title FROM com.acme.Book WHERE author = :authorName AND publicationYear = :publicationYear").build();

// Set actual parameter values
query.setParameter("authorName", "Doe");
query.setParameter("publicationYear", 2010);

// Execute the query
List<Book> found = query.list();

或者,您可以提供一个实际参数值映射以一次性设置多个参数: ⁠

一次设置多个命名参数

Map<String, Object> parameterMap = new HashMap<>();
parameterMap.put("authorName", "Doe");
parameterMap.put("publicationYear", 2010);

query.setParameters(parameterMap);

注意

在首次使用参数执行查询时,执行查询解析、验证和执行规划工作的主要部分。与使用恒定值而不是查询参数类似的查询相比,后续执行期间不会重复这一工作,从而提高性能。

11.3.5. Ickle Query Language Parser Syntax

Ickle 查询语言是 JPQL 查询语言的小子集,具有一些全文本扩展。

解析器语法有一些值得注意的规则:

  • 空格并不重要。
  • 字段名称不支持通配符。
  • 必须始终指定字段名称或路径,因为没有默认字段。
  • &&|| 在全文本和 JPA predicates 中都接受 ANDOR
  • ! 可以被使用,而不是
  • 缺少布尔值运算符解释为 OR
  • 字符串术语必须用单引号或双引号括起。
  • Fuzziness 和 boosting 没有被任意顺序接受;fuzziness 始终是首先接受的。
  • != 被接受,而不是 <& gt;
  • boosting 无法应用到 >, &gt;=, & lt;, HBAC operators。范围可用于实现相同的结果。

11.3.5.1. 过滤 Operator

Ickle 支持许多可用于索引和非索引字段的过滤运算符。

Operator描述Example

in

检查左侧运算对象是否等于所给值集合中的一个元素。

FROM Book WHERE isbn IN ('ZZ', 'X1234')

like

检查左侧参数(预期为 String)是否匹配 JPA 规则之后的通配符模式。

FROM Book WHERE 标题 LIKE '%Java%'

=

检查 left 参数是否与给定值完全匹配

FROM Book WHERE name = 'Programming Java'

!=

检查 left 参数与给定值不同

FROM Book WHERE 语言 != ' English'

>

检查 left 参数是否大于给定值。

FROM Book WHERE price > 20

>=

检查 left 参数是否大于或等于给定值。

FROM Book WHERE price >= 20

<

检查 left 参数是否小于给定值。

FROM Book WHERE year < 2012

检查 left 参数是否小于或等于给定值。

FROM Book WHERE price 了 50

between

检查 left 参数是否在给定的范围限值之间。

FROM Book WHERE 价格 BETWEEN 50 AND 100

11.3.5.2. 布尔值条件

以下示例中演示了多个属性条件和逻辑组合()和 disjunction ()运算符,以创建更复杂的条件。布尔值运算符的已知运算符优先级规则适用于此处,因此操作器的顺序无关。这里 运算符的优先级比 高,即使先调用

# match all books that have "Data Grid" in their title
# or have an author named "Manik" and their description contains "clustering"

FROM com.acme.Book WHERE title LIKE '%Data Grid%' OR author.name = 'Manik' AND description like '%clustering%'

布尔值负值在逻辑运算符之间具有最高优先级,并且只适用于下一个简单的属性条件。

# match all books that do not have "Data Grid" in their title and are authored by "Manik"
FROM com.acme.Book WHERE title != 'Data Grid' AND author.name = 'Manik'

11.3.5.3. 嵌套条件

通过括号更改逻辑运算符的优先级:

# match all books that have an author named "Manik" and their title contains
# "Data Grid" or their description contains "clustering"
FROM com.acme.Book WHERE author.name = 'Manik' AND ( title like '%Data Grid%' OR description like '% clustering%')

11.3.5.4. 选择属性

在某些用例中,如果应用实际使用了一小部分属性,则返回整个域对象是过量的,特别是在域实体有嵌入式实体时。查询语言允许您指定属性(或属性路径)的子集来返回 - 投射。如果使用投射,则 QueryResult.list () 不会返回整个域实体,而是返回 Object[] 列表,则数组中的每个插槽都与投射属性对应。

# match all books that have "Data Grid" in their title or description
# and return only their title and publication year
SELECT title, publicationYear FROM com.acme.Book WHERE title like '%Data Grid%' OR description like '%Data Grid%'

11.3.5.5. 排序

使用 ORDER BY 子句,根据一个或多个属性或属性路径对结果进行排序。如果指定了多个排序条件,则顺序将指定其优先级。

# match all books that have "Data Grid" in their title or description
# and return them sorted by the publication year and title
FROM com.acme.Book WHERE title like '%Data Grid%' ORDER BY publicationYear DESC, title ASC

11.3.5.6. 分组和聚合

Data Grid 能够根据一组分组字段并构造来自每个组的结果聚合来对查询结果进行分组,方法是将聚合应用到每个组中的值集合。分组和聚合只能应用到投射查询(在 SELECT 子句中带有一个或多个字段)。

支持的聚合有: avg、sum、count、max、min。

组分组字段通过 GROUP BY 子句指定,并且用于定义分组字段的顺序无关。投射中选择的所有字段都必须分组字段,否则必须使用下面描述的分组功能之一来聚合它们。项目字段可以聚合,并同时用于分组。选择仅分组字段但没有聚合字段的查询是法律的。附录示例:作者对手册进行分组,并计算它们。

SELECT author, COUNT(title) FROM com.acme.Book WHERE title LIKE '%engine%' GROUP BY author
注意

一个投射查询,所有选择的字段都应用了聚合功能,且无法用于分组的字段。在这种情况下,聚合将全局计算,就像有一个全局组一样。

11.3.5.7. 聚合

以下聚合功能可应用到字段:

  • avg () - 计算一组数字的平均数量。接受的值是原始数字和 java.lang.Number 的实例。结果以 java.lang.Double 表示。如果没有非 null 值,则结果为 null
  • count () - 计算非null 行的数量并返回 java.lang.Long。如果没有非 null 值,则 结果为 0。
  • max () - 返回找到的最大值。接受的值必须是 java.lang.Comparable 的实例。如果没有非 null 值,则结果为 null
  • min () - 返回找到的最小值。接受的值必须是 java.lang.Comparable 的实例。如果没有非 null 值,则结果为 null
  • sum () - 计算一组数字的总和。如果没有非 null 值,则结果为 null。下表根据指定字段显示返回类型。
表 11.1. 表和返回类型
字段类型返回类型

不可或缺(除 BigInteger)

Long

float 或 Double

�

BigInteger

BigInteger

BigDecimal

BigDecimal

11.3.5.8. 使用分组和聚合评估查询

聚合查询可以包含过滤条件,如常规查询。可以在两个阶段执行过滤:在分组操作之前和之后执行。在执行分组操作之前,定义的所有过滤器条件都将应用到缓存条目(而不是最终投射)。这些过滤器条件可以引用查询的实体类型的任何字段,旨在限制要作为分组阶段输入的数据集。调用 groupBy () 方法后定义的所有过滤器条件将应用到投射结果和分组操作。这些过滤器条件可以引用任何 groupBy () 字段或聚合的字段。允许引用在 select 子句中指定的聚合字段,但禁止引用非aggregated 和 non-grouping 字段。在此阶段过滤将根据其属性减少组量。排序也可以指定,类似于常见的查询。排序操作在分组操作后执行,并可引用任何 groupBy () 字段或聚合字段。

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.