简体   繁体   English

如何通过nextPageToken实现分页?

[英]How to implement pagination by nextPageToken?

I am trying to implement pagination using nextPageToken.我正在尝试使用 nextPageToken 实现分页。

I have table:我有表:

CREATE TABLE IF NOT EXISTS categories
(
    id        BIGINT PRIMARY KEY,
    name      VARCHAR(30) NOT NULL,
    parent_id BIGINT REFERENCES categories (id)
);

so I have entity Category:所以我有实体类别:

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;
    @Column(name = "name")
    private String name;
    @OneToOne
    @JoinColumn(name = "parent_id", referencedColumnName = "id")
    private Category category;

I dont really understand what I have to do next.我真的不明白我接下来要做什么。 client requests token(that keeps what?)客户端请求令牌(保留什么?)

Assume I have controller:假设我有控制器:

@GetMapping
    public ResponseEntity<CategoriesTokenResponse> getCategories(
            @RequestParam String nextPageToken
    ) {
        return ResponseEntity.ok(categoryService.getCategories(nextPageToken));
    }

Service:服务:

public CategoriesTokenResponse getCategories(String nextPageToken) {
        return new CategoriesTokenResponse(categoryDtoList, "myToken");
    }
@Data
@AllArgsConstructor
public class CategoriesTokenResponse {
    private final List<CategoryDto> categories;
    private final String token;
}

How I have to implement sql query for that?我必须如何为此实现 sql 查询? And how I have to generate nextPagetoken for each id?以及如何为每个 id 生成 nextPagetoken?

SELECT * FROM categories WHERE parent_id = what?
AND max(category id from previous page = token?)
ORDER BY id LIMIT 20;

First, you need to understand what you are working with here.首先,您需要了解您在这里使用的是什么。 Every implementation has some sort of limitation or inefficiency.每个实现都有某种限制或效率低下。 For example, using page tokens like that is only good for infinite scroll pages.例如,使用这样的页面标记仅适用于无限滚动页面。 You can't jump to any specific page.您无法跳转到任何特定页面。 So if my browser crashes and I'm on page 100, I have to scroll through 100 pages AGAIN.因此,如果我的浏览器崩溃并且我在第 100 页,我必须再次滚动浏览 100 页。 It is faster for massive data sets for sure, but does that matter if you need access to all pages?对于海量数据集来说肯定更快,但是如果您需要访问所有页面,这有关系吗? Or if you limit the return to begin with?或者,如果您从一开始就限制回报? Such as only getting the first 30 pages?比如只获取前30页?

Basically decide this: Do you only care about the first few pages because search/sort is always in use?基本上决定这个:你只关心前几页,因为搜索/排序总是在使用吗? (like a user never using more than the first 1-5 pages of google) and is that data set large? (就像用户从不使用超过 google 的前 1-5 页)并且该数据集很大吗? Then great use-case.然后是很好的用例。 Will a user select "all items in the last 6 months" and actually need all of them or is the sort/search weak?用户是否会选择“过去 6 个月内的所有项目”并且实际上需要所有项目,还是排序/搜索很弱? Or, will you return all pages and not limit max return of 30 pages?或者,您会返回所有页面而不限制最多返回 30 页吗? Or, is development speed more important than a 0.1-3 second (depends on data size) speed increase?或者,开发速度是否比 0.1-3 秒(取决于数据大小)速度增加更重要? Then go with built in JPA Page objects.然后使用内置的 JPA Page 对象。

I have used Page objects on 700k records with less than a second speed change compared to 70k records.与 70k 记录相比,我在 700k 记录上使用了 Page 对象,速度变化不到一秒。 Based on that, I don't see removing offset adding a ton of value unless you plan for a huge data set.基于此,除非您计划使用庞大的数据集,否则我认为移除偏移量不会增加大量价值。 I just tested a new system I'm making with pageable, it returned 10 items on page 1 in 84 milliseconds with no page limiter for 27k records on a vpn into my work network from my house.我刚刚测试了一个我正在使用 pageable 制作的新系统,它在 84 毫秒内返回了第 1 页上的 10 个项目,并且没有页面限制器,用于从我家到我的工作网络的 vpn 上的 27k 记录。 A table with over 500k records took 131 milliseconds That's pretty fast.一个包含超过 500k 条记录的表需要 131 毫秒,这非常快。 Want to make it faster?想让它更快? Force a total max return of 30 pages and a max of 100 results per page, because normally, they don't need all data in that table.强制总共最大返回 30 页和每页最多 100 个结果,因为通常情况下,他们不需要该表中的所有数据。 They want something else?他们想要别的东西? refine the search.细化搜索。 The speed difference is less than a second between this and the seek/key stype paging.这与搜索/键 stype 分页之间的速度差异不到一秒。 This is assuming a normal SQL database too.这也是假设一个普通的 SQL 数据库。 NoSQL is a bit different here. NoSQL 在这里有点不同。 Baeldung has a ton of articles on jpa paging like the following: https://www.baeldung.com/rest-api-pagination-in-spring Baeldung 有大量关于 jpa 分页的文章,如下所示: https ://www.baeldung.com/rest-api-pagination-in-spring

JPA Paging should take no more than 30 minutes to learn and implement, it's extremely easy and comes stock on JPA repositories. JPA Paging 的学习和实现时间不应超过 30 分钟,它非常简单,并且在 JPA 存储库中提供。 I strongly suggest using that over the seek/key style paging as you likely aren't building a system like google's or facebook's.我强烈建议在搜索/键样式分页上使用它,因为您可能没有构建像 google 或 facebook 那样的系统。

If you absolutely want to go with the seek/key style paging there's a good informational page here: https://blog.jooq.org/2013/10/26/faster-sql-paging-with-jooq-using-the-seek-method/如果您绝对想使用搜索/键样式分页,这里有一个很好的信息页面: https : //blog.jooq.org/2013/10/26/faster-sql-paging-with-jooq-using-the-寻找方法/

In general, what you are looking for is using JOOQ with spring.一般来说,您正在寻找的是将 JOOQ 与 spring 一起使用。 Implementation example here: https://docs.spring.io/spring-boot/docs/1.3.5.RELEASE/reference/html/boot-features-jooq.html这里的实现示例: https : //docs.spring.io/spring-boot/docs/1.3.5.RELEASE/reference/html/boot-features-jooq.html

Basically, create a DSL context:基本上,创建一个 DSL 上下文:

private final DSLContext DSL;

@Autowired
public JooqExample(DSLContext dslContext) {
    this.DSL= dslContext;
}

Then use it like so:然后像这样使用它:

DSL.using(configuration)
   .select(PLAYERS.PLAYER_ID,
           PLAYERS.FIRST_NAME,
           PLAYERS.LAST_NAME,
           PLAYERS.SCORE)
   .from(PLAYERS)
   .where(PLAYERS.GAME_ID.eq(42))
   .orderBy(PLAYERS.SCORE.desc(),
            PLAYERS.PLAYER_ID.asc())
   .seek(949, 15) // (!)
   .limit(10)
   .fetch();

Instead of explicitly phrasing the seek predicate, just pass the last record from the previous query, and jOOQ will see that all records before and including this record are skipped, given the ORDER BY clause.没有明确地表达搜索谓词,只需传递上一个查询的最后一条记录,jOOQ 将看到在给定 ORDER BY 子句的情况下跳过该记录之前和包括该记录的所有记录。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM