MongoDB根据Document中的List类型的Field分页查询 -- Java

63 阅读2分钟

一、需求场景

就是个列表展示的分页查询,只不过数据是存在MongoDB中的,存的格式如下:

{
  "modifyUser": "test",
  "createUser": "test",
  "action":"SKIP"
  "detail": [
    "1234",
    "5938",
    "6189",
    "6549",
    "7932",
    "7933",
    // 此处省略若干条
    .......
  ]
},
{
  "modifyUser": "test",
  "createUser": "test",
  "action":"INCLUDE"
  "detail": [
    "7696",
    "0986",
    "7654",
    "0985",
    "3457",
    "0985",
    // 此处省略若干条
    .......
  ]
}

前台页面要求如下展示:

image.png

这意味着要根据数据库中每一条数据的detail字段进行分页查询。

二、实现方案

话不多说,直接看最终的实现方案:

public List<DO> pageQuery(Request request){
    
    // 根据自己的入参构造查询条件
    Criteria criteria = buildCriteria(request);

    Aggregation aggregation = Aggregation.newAggregation(
            match(criteria),
            unwind("detail", true),
            sort(Sort.Direction.ASC, "detail"),
            skip((queryRequest.getPageIndex().longValue() - 1) * queryRequest.getPageSize()),
            limit(queryRequest.getPageSize())
    );

    return mongoTemplate.aggregate(aggregation, "table", DO.class).getMappedResults();
}

三、涨点知识

aggregate()是MongoDB的聚合函数,Aggregation是与之对应的聚合框架,主要用于对多个document的数据进行各种聚合计算,以返回最终需要的结果。

以上面的数据和实现方案为例,看看每一步都做了些什么?

 Aggregation aggregation = Aggregation.newAggregation(
        match(criteria),
        unwind("detail", true),
        sort(Sort.Direction.ASC, "detail"),
        skip((queryRequest.getPageIndex().longValue() - 1) * queryRequest.getPageSize()),
        limit(queryRequest.getPageSize())
);

将上述代码转换为MongoDB的SQL:

db.test_table.aggregate(
    [
        { $match : {action:"SKIP"} },
        { $unwind: {path: "$detail",preserveNullAndEmptyArrays: true} },
        { $sort: {"detail"} },
        { $skip: 0 },
        { $limit: 10 },
    ] );

主要看一下前两步做了什么:

$match匹配过滤条件,将符合条件的文档筛选出来,$unwind将筛选后的结果中的detail进行拆分,每一条包含一个数组中的值。再经过排序,限制输出条数等操作,得到我们想要的结果。

image.png

MongoDB中常用的聚合操作:

操作说明与SQL对照
$match过滤数据,筛选出符合条件的文档WHERE
$project修改输入文档的结构。可以用来重命名、增加或删除fieldSELECT
$unwind将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值
$limit用来限制MongoDB聚合管道返回的文档数LIMIT
$skip在聚合管道中跳过指定数量的文档
$group将集合中的文档分组GROUP BY
$sort将输入文档排序后输出ORDER BY
$lookup连表查询,将被关联集合添加到执行操作的集合中JOIN