reactive 编程+redisson 如何分页的问题

4 天前
 bleulucaswu
    @Bean
    public RouterFunction<ServerResponse> route(CacheHandler cacheHandler) {
        return RouterFunctions.route()
                .GET("......", cacheHandler::xxxxxxx)
                .build();

所以这个该咋做啊 -

814 次点击
所在节点    程序员
11 条回复
bleulucaswu
4 天前
要做分页的原因是 redis search 这个是强制分页的 (ft.search index *)就你查询默认只给你 10 个
所以必须 (ft.search index * 0 100) 就是必须给个 offset count 参数
ZGame
4 天前
请求所有数据可以通过 merge ,zip 等操作符吧, 另外可以看看 hs-web ,用的就是响应式。响应式更多时候有点像函数式编程,看看你的操作能不能通过函数式的方式,关注入参出参,还有函数转换方法,尽量减少副作用和外部的变量直接传入,so.. 其实你会发现用不好比用命令式的方式写代码更难受
OctVan
4 天前
https://projectreactor.io/docs/core/release/reference/#sinks
可以用这个一直翻页,直到取完数据
spkingr
4 天前
遇事不决问 AI ,这种问题问 AI 最好,他都能给你写好。
编程式风格确实不推荐使用 for 循环,用 for 也是配合 yield 。
你这个 flatMap 按理来说应该是可以的,我复制你的问题给 AI ,AI 就简单的给了一个参考代码,你可以看看,看能不能改改用上:

public Mono<SearchResult> searchWithPagination(int pageNumber, int pageSize) {
return redissonReactiveClient.getSearch(StringCodec.INSTANCE)
.search(SearchArgs(pageNumber, pageSize)) // 返回是 Mono<SearchResult>,有条数和页数吧
.flatMap(initialSearchResult -> { // flatMap 抽取结果
int totalPages = initialSearchResult.getTotal() / pageSize; // 修改一下,获取页数
if (pageNumber < totalPages) {
// 这里继续查询并合并
return redissonReactiveClient.getSearch(StringCodec.INSTANCE)
.search(SearchArgs(pageNumber, pageSize))
// map 则是转换结果
.map(nextSearchResult -> combineSearchResults(initialSearchResult, nextSearchResult));
} else {
// 没有数据
return Mono.just(initialSearchResult);
}
});
}

private SearchResult combineSearchResults(SearchResult initialResult, SearchResult nextResult) {
List<Document> combinedDocuments = new ArrayList<>(initialResult.getDocuments());
combinedDocuments.addAll(nextResult.getDocuments());
SearchResult combinedResult = new SearchResult();
combinedResult.setTotal(initialResult.getTotal());
combinedResult.setDocuments(combinedDocuments);
return combinedResult;
}
spkingr
4 天前
可以用 MD 吗:

```
public Mono<SearchResult> searchWithPagination(int pageNumber, int pageSize) {
return redissonReactiveClient.getSearch(StringCodec.INSTANCE)
.search(SearchArgs(pageNumber, pageSize)) // 返回是 Mono<SearchResult>,有条数和页数吧
.flatMap(initialSearchResult -> { // flatMap 抽取结果
int totalPages = initialSearchResult.getTotal() / pageSize; // 修改一下,获取页数
if (pageNumber < totalPages) {
// 这里继续查询并合并
return redissonReactiveClient.getSearch(StringCodec.INSTANCE)
.search(SearchArgs(pageNumber, pageSize))
// map 则是转换结果
.map(nextSearchResult -> combineSearchResults(initialSearchResult, nextSearchResult));
} else {
// 没有数据
return Mono.just(initialSearchResult);
}
});
}

private SearchResult combineSearchResults(SearchResult initialResult, SearchResult nextResult) {
List<Document> combinedDocuments = new ArrayList<>(initialResult.getDocuments());
combinedDocuments.addAll(nextResult.getDocuments());
SearchResult combinedResult = new SearchResult();
combinedResult.setTotal(initialResult.getTotal());
combinedResult.setDocuments(combinedDocuments);
return combinedResult;
}

```
yazinnnn0
4 天前
这个效果?


用的 mutiny, 跟 reactor 差不多
拿到 total 的 mono 时做 flatmap 转换, 然后把你的循环查询转换称序列+步进(都用 fp 了就别用传统 for 循环了...
然后把序列做 fold 操作, java 里貌似需要用 reduce 去实现, fold 的初始值设置为 mono 形式的零值, 比如 Mono.just(List.empty())之类, fold 的 operation 去合并 acc 和新查出来的值(mutiny 用 combine, reactor 里应该有类似的 api)
bleulucaswu
3 天前
@spkingr 这样是没错 可是如果 search 操作不止就两次呢 就不止向 redis 请求两次 我主要想请教下 reative 风格的编程中 循环 x 操作该怎么做 且 x 是异步执行在循环之外的一个线程中 然后 Xn 的部分参数和 Xn-1 有关 然后就是如果 Xn 触发了某个条件 如何让 Xn+1 Xn+2 ... 全部取消 X1~Xn 都是异步无前后顺序执行的 该怎么做到有序的取消操作
bleulucaswu
3 天前
@yazinnnn0 兄弟 图裂了
spkingr
3 天前
@bleulucaswu 这个时候不得不提 CompletableFuture 大法好了!
thenCombine/thenCompose/thenApplyAsync 这些方法很好用,建议参考这篇文章: https://tech.meituan.com/2022/05/12/principles-and-practices-of-completablefuture.html
bleulucaswu
5 小时 10 分钟前
@yazinnnn0 请问下 如果 fold 里每次 search 操作都在一个额外的线程中进行,可以做到把结果 combine 到一起吗
然后你这是 0..<20 step 5 来做循环的,假设 index=10 那次循环,因为触发了某个条件将它强制停止,有什么办法让 index=15 的那次循环以及之后所有的循环全部停止不做了(如果有的话),因为每次循环都是多线程乱序的,这能做到吗用 mutiny
reactive 编程我还不熟悉 感觉用起来太难了
bleulucaswu
5 小时 6 分钟前
@yazinnnn0 就类似
(1..<all step 5).fold(initial) { 多线程操作 }.until( index > 10 )
就 index>10 的所有多线程里的操作都停掉,until 中肯定会有更复杂的判断条件,这里就举个例子

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1079060

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX