MongoDB aggregate 管道聚合查询

数据准备

UserPO

@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "user")
public class UserPO extends BasePO {

    private String name;

    private String description;

}

UserGroupPO

@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "user_group")
public class UserGroupPO extends BasePO {

    private String name;

    private String description;

    private List<Long> userIds;

}

用户数据
在这里插入图片描述

用户组数据
在这里插入图片描述

 

条件查询

match:and 匹配
查询用户组 id 等于 1,且删除标识等于 N 的数据

db.getCollection("user_group").aggregate([{
    "$match": {
        "$and": [{
            "_id": NumberLong("1")
        }, {
            "deleteFlag": "N"
        }]
    }
}]);

match:or 匹配
查询用户 name 等于 nn 或者 description 等于 dd 的数据

db.getCollection("user").aggregate([{
    "$match": {
        "$or": [{
            "name": "nn"
        }, {
            "description": "dd"
        }]
    }
}]);

 

聚合查询

查询用户组里的用户详情

模糊查询

match:按规则匹配
regex:按正则匹配
实现:按 xxx 模糊匹配字段 userName 或者 按 xxx 模糊匹配字段 userDes

db.getCollection("user").aggregate([{
   "$match": {
       "$or": [{
           "userName": {
               "$regex": ".*xxx.*"
           }
       }, {
           "userDes": {
               "$regex": ".*xxx.*"
           }
       }]
   }
}]);

 

拆分数据

unwind:将文档中的某一个数组类型字段拆分成多条
实现:根据 userIds 把用户组拆分了多行

db.getCollection("user_group").aggregate([{
    "$match": {
        "$and": [{
            "_id": NumberLong("2809813774582045833")
        }, {
            "deleteFlag": "N"
        }]
    }
}, {
    "$unwind": "$userIds"
}]);

在这里插入图片描述
 

关联查询

根据用户组查询用户

lookup官方文档
lookup:关联查询,类似于 MySQL 的 left jion 效果
实现:根据用户组的 userIds 查询用户详情,注意:查出来的 user 是个数组

  • from:同一个数据库下等待被Join的集合。
  • localField:源集合中的match值,如果输入的集合中,某文档没有 localField
    这个Key(Field),在处理的过程中,会默认为此文档含
    有 localField:null的键值对。
  • foreignField:待Join的集合的match值,如果待Join的集合中,文档没有foreignField
    值,在处理的过程中,会默认为此文档含有 foreignField:null的键值对。
  • as:为输出文档的新增值命名。如果输入的集合中已存在该值,则会覆盖掉
db.getCollection("user_group").aggregate([{
    "$match": {
        "$and": [{
            "_id": NumberLong("4523281346310580824")
        }, {
            "deleteFlag": "N"
        }]
    }
}, {
    "$unwind": "$userIds"
}, {
    "$lookup": {
        "from": "user",
        "localField": "userIds",
        "foreignField": "_id",
        "as": "user"
    }
}]);

在这里插入图片描述

 

根据用户查询用户组

lookup:关联查询,类似于 MySQL 的 left jion 效果
实现:查询用户列表且包含对应的用户组信息,注意:查出来的 userGroups 是个数组

  • from:要关联的从表名
  • let:自定义变量,可以为多个
  • pipeline:自定义的操作从表的聚合,但不允许使用out和merge操作,使用 let 定义的变量需要用两个$
  • as:为输出文档的新增值命名。如果输入的集合中已存在该值,则会覆盖掉
db.getCollection("user").aggregate([{
    $lookup: {
        from: "user_group",
        let: {
            user_id: "$_id"
        },
        pipeline: [
            {
                $match: {
                    $expr: {
                        $in: ["$$user_id", "$userIds"]
                    }
                }
            }
        ],
        as: "userGroups"
    }
}]);

在这里插入图片描述

 

控制显示

project 控制字段显示与否
实现: 删除无用字段,

  • 普通列({成员:1 | true}):表示要显示的内容
  • “_id” 列({“_id”:0 | false}):表示 “_id” 列是否显示
db.getCollection("user_group").aggregate([{
    "$match": {
        "$and": [{
            "_id": NumberLong("4523281346310580824")
        }, {
            "deleteFlag": "N"
        }]
    }
}, {
    "$unwind": "$userIds"
}, {
    "$lookup": {
        "from": "user",
        "localField": "userIds",
        "foreignField": "_id",
        "as": "user"
    }
}, {
    "$project": {
        "user": 1,
        "_id": 0,
        
    }
}]);

在这里插入图片描述
 

字段置顶

arrayElemAt:将指定文档提升到顶级并替换所有其它字段。该操作会替换输入文档中的所有现在字段,包括_id字段
replaceRoot:返回存在于给定数组的指定索引上的元素
实现:把 user 的第一个元素提至顶级

db.getCollection("user_group").aggregate([{
    "$match": {
        "$and": [{
            "_id": NumberLong("4523281346310580824")
        }, {
            "deleteFlag": "N"
        }]
    }
}, {
    "$unwind": "$userIds"
}, {
    "$lookup": {
        "from": "user",
        "localField": "userIds",
        "foreignField": "_id",
        "as": "user"
    }
}, {
    "$project": {
        "user": 1,
        "_id": 0,
        
    }
}, {
    "$replaceRoot": {
        "newRoot": {
            "$arrayElemAt": ["$user", 0]
        }
    }
}]);

在这里插入图片描述
此数据格式已经非常漂亮,符合日常返回格式,完成了需求

 

合并字段

mergeObjects:将多个文档合并为一个文档,如果要合并的文档包含相同的字段名,则结果文档中的字段具有该字段最后一个合并文档中的值
实现:保留 userGroup 的信息

db.getCollection("user_group").aggregate([{
    "$match": {
        "$and": [{
            "_id": NumberLong("4523281346310580824")
        }, {
            "deleteFlag": "N"
        }]
    }
}, {
    "$unwind": "$userIds"
}, {
    "$lookup": {
        "from": "user",
        "localField": "userIds",
        "foreignField": "_id",
        "as": "user"
    }
}, {
    "$replaceRoot": {
        "newRoot": {
            "$mergeObjects": [{
                "$arrayElemAt": ["$user", 0]
            }, "$$ROOT"]
        }
    }
},{
    "$project": {
        "user": 0
    }
}]);

在这里插入图片描述
 

新增或修改字段

set:字段存在则修改,无则新增
实现:

db.getCollection("user_group").aggregate([{
    "$match": {
        "$and": [{
            "_id": NumberLong("4523281346310580824")
        }, {
            "deleteFlag": "N"
        }]
    }
}, {
    "$unwind": "$userIds"
}, {
    "$lookup": {
        "from": "user",
        "localField": "userIds",
        "foreignField": "_id",
        "as": "user"
    }
}, {
    "$replaceRoot": {
        "newRoot": {
            "$mergeObjects": [{
                "$arrayElemAt": ["$user", 0]
            }, "$$ROOT"]
        }
    }
}, {
    "$project": {
        "user": 0
    }
}, {
    "$set": {
        "accounts": "accounts",
        "deleteFlag": "deleteFlag"
    }
}]);

在这里插入图片描述
 

计算总数

count:计算总数
实现:查询 user 表的总条数

db.getCollection("user").aggregate([
    {
        "$count": "total"
    }
]);

在这里插入图片描述

 

分页查询

分页:对数据做分页处理
跳过 3 条数据,从第 4 条起,显示 2 条

  • skip:跳过多少条
  • limit:显示多少条
db.getCollection("user").aggregate([
    {
        "$skip": 3
    },
    {
        "$limit": 2
    }
]);

在这里插入图片描述
 

分页查询加总数

分页查询需要同时返回总数和数据
facet:在同一组输入文档的单一阶段中处理多个聚合管道;每个子管道在输出文档中都有自己的字段,其结果存储在文档数组中

db.getCollection("user").aggregate([
    {
        "$facet": {
            "metadata": [{
                "$count": "total"
            }],
            "records": [{
                "$skip": 0
            }, {
                "$limit": 10
            }]
        }
    }
]);

在这里插入图片描述
metadata 不太符合常规数据结构,把它去掉,把 total 提上顶层

db.getCollection("user").aggregate([
    {
        "$facet": {
            "metadata": [{
                "$count": "total"
            }],
            "records": [{
                "$skip": 0
            }, {
                "$limit": 2
            }]
        }
    },
    {
        "$replaceRoot": {
            "newRoot": {
                "$mergeObjects": [{
                    "$arrayElemAt": ["$metadata", 0]
                }, "$$ROOT"]
            }
        }
    },
    {
        "$project": {
            "metadata": 0
        }
    }
]);

在这里插入图片描述
 

排序

sort:根据某字段对数据进行排序
其中 key 用来定义要根据那个字段进行排序,后面的值 1 则表示以升序进行排序,若要以降序进行排序则需要将其设置为 -1
实现:对用户表按创建时间倒序来排序

db.getCollection("user").aggregate([
    {
        $sort: {
            creationDate: - 1
        }
    }
]);

 

分组

$group :根据某字段对数据进行分组,类似 MySQL的 group by

  • _id :强制必须存在。可以为 null
  • $sum:计算总数
  • $avg:计算平均值
  • $max:最大值
  • $min:最小值
  • $first:输出第一个内容
  • $last:输出最后一个内容
  • $push:将数据拼接到一个数组中
  • $addToSet:将数据拼接到一个数组中,过滤重复数据

数据准备
在这里插入图片描述

 
$sum:根据用户的 userName 字段,对数据进行分组,并统计重复的总数

db.getCollection("user").aggregate([{
    $group: {
        _id: "$userName",
        count: {
            $sum: 1
        }
    }
}]);

在这里插入图片描述
 
$avg:根据用户的 userName 字段,对数据进行分组,并算出分组后 userDes 的平均值

db.getCollection("user").aggregate([{
    $group: {
        _id: "$userName",
        desavg: {
            $avg: "$userDes"
        }
    }
}]);

在这里插入图片描述
 
$push:根据用户的 userName 字段,对数据进行分组,并把 userDes 组合到 num

db.getCollection("user").aggregate([{
    $group: {
        _id: "$userName",
        num: {
            $push: "$userDes"
        }
    }
}]);

在这里插入图片描述
 
$addToSet:和push类似,但会过滤重复的数据,name2 的 40 只有一条了

db.getCollection("user").aggregate([{
    $group: {
        _id: "$userName",
        num: {
            $addToSet: "$userDes"
        }
    }
}]);

在这里插入图片描述
 
$$ROOT:分组后生成list

db.getCollection("user").aggregate([{
    $group: {
        _id: "$userName",
        num: {
            $push: "$$ROOT"
        }
    }
}]);

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值