这段内容讲的是 Apache Ignite 中的 Scan Query(扫描查询) 的使用方式,以下是对内容的详细中文解释:
一、Scan Query 概述
IgniteCache
提供了多种查询方法,其中 ScanQuery 是一种简单的分布式查询方式,可以用来遍历缓存中的所有条目(key-value)。如果不加过滤条件,它会返回整个缓存的数据。
二、Query 和 QueryCursor
Query
:代表一个分页查询任务,可以通过Query.setPageSize(...)
设置每页返回的条目数,默认是 1024。QueryCursor
:代表查询结果集,它支持分页遍历。当你遍历到最后一页时,它会自动在后台请求下一页数据。- 如果不需要分页,可以直接调用
QueryCursor.getAll()
方法一次性获取所有结果。
- 如果不需要分页,可以直接调用
三、关闭游标(Closing Cursors)
- 调用
getAll()
时,QueryCursor
会自动关闭。 - 如果是使用
for
循环或者显式获取Iterator
来遍历结果,必须手动关闭游标,推荐使用 try-with-resources 语句块来确保资源释放。
四、执行 Scan Query
1. 无过滤条件的 Scan Query
IgniteCache<Integer, Person> cache = ignite.getOrCreateCache("myCache");
QueryCursor<Cache.Entry<Integer, Person>> cursor = cache.query(new ScanQuery<>());
这段代码会从缓存中取出所有条目。
2. 带过滤条件的 Scan Query
你可以传入一个谓词(IgniteBiPredicate
)来过滤数据。这个谓词会在远程节点上执行。
IgniteBiPredicate<Integer, Person> filter = (key, p) -> p.getSalary() > 1000;
try (QueryCursor<Cache.Entry<Integer, Person>> qryCursor = cache.query(new ScanQuery<>(filter))) {
qryCursor.forEach(entry -> System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()));
}
这段代码会找出工资大于 1000 的 Person 对象。
3. 使用 Transformer(转换器)
ScanQuery 还支持一个可选的转换器(Transformer),可以在服务端将数据转换后再返回,减少网络传输。
List<Integer> keys = cache.query(new ScanQuery<>(
(k, p) -> p.getSalary() > 1000),
(entry) -> entry.getKey()).getAll();
这个例子中,只返回符合条件的 key,不传输 value,节省网络流量。
五、本地 Scan Query(Local Scan Query)
默认情况下,Scan Query 是在所有节点上执行的(分布式查询),但你可以设置 .setLocal(true)
,让查询只在本地节点执行。
QueryCursor<Cache.Entry<Integer, Person>> cursor = cache
.query(new ScanQuery<Integer, Person>().setLocal(true));
- 适用于只关心本地节点缓存数据的场景。
- 例如:每个节点只处理自己的本地数据,不跨节点查询。
总结
功能 | 描述 |
---|---|
ScanQuery | 分布式扫描缓存中的数据 |
Predicate | 在远程节点上过滤数据 |
Transformer | 在远程节点上转换数据再返回,减少网络传输 |
QueryCursor | 支持分页遍历,需要正确关闭 |
setLocal(true) | 只在本地节点执行查询 |
如果你在使用 Ignite 缓存,并需要遍历数据或做简单的过滤,ScanQuery 是一种简单高效的选择。对于更复杂的查询,可以使用 SQL Query。