MongoDB : Java 日常开发有这一篇手记就够了

👈👈👈 欢迎点赞收藏关注哟

首先分享之前的所有文章 >>>> 😜😜😜
文章合集 : 🎁 juejin.cn/post/694164...
Github : 👉 github.com/black-ant
CASE 备份 : 👉 gitee.com/antblack/ca...

一. 前言

日常业务中时不时会用到一些 MongoDB 的查询,慢慢的也累计了不少,索性整理了一下

MongoDB Client 核心原理

juejin.cn/post/725325...

思路梳理

  • 简单查询 : 通过 find 触发查询,运算符包括 eq 等查询规约
  • 合并查询 : 通过 and , or 做联合查询
  • 高级查询 : MongoDB 提供了大量的查询 ,这些查询在官网都能找到案例

Java 使用思路

文章中会穿插对应 Java 的查询写法 ,在日常 Java 开发中对 MongoDB 的使用主要有以下几种 :

  • 使用 SpringData Repository 体系进行简单查询
  • 在 SpringData 的基础上使用 ExampleMatcher 进行复杂查询
  • 在 SpringData 的基础上使用 MongoTemplate 进行定制查询
    • MongoTemplate 的查询语法主要是 Bson ,以下案例也主要以 Bson 为主
    • Bson 语法可以用于构建和操作 BSON 文档

二.常用操作

MongoDB 关键字 (官方更加清晰)

  • 比较查询 : eq / ge / gte / lt / lte / ne / nin
  • 逻辑查询 : and / or / not / nor
  • 元素查询 : exists / type (查询数据类型)
  • 表达式查询 : expr / jsonSchema / text / where
    • mod : 取模查询,查找某个字段的值除以指定的除数后余数等于指定余数的文档
    • regex : 执行正则表达式匹配
  • 地理空间查询 :
    • near : 离指定地理点最近
    • geoWithin : 查找指定区域内的文档
    • geoIntersects : 与指定区域相交的文档
    • nearSphere : 球面几何查询
    • box : 查询矩形框内的文档
  • 数组查询 :
    • all : 查找包含指定数组中的所有元素的文档
    • elemMatch : 数组匹配怕, 配置数组中是否包含该字段
    • size : 用于筛选包含指定数组大小的文档

其他的就不看了,官方文档很清晰。

2.1 简单查询

java 复制代码
// 按照属性查询
db.getCollection("test").find({"name" : "name"})

// 比较运算符
大于 : db.col.find({age : {$gt : 100}})
小于 : db.col.find({age : {$lte : 150}})
区间 : db.col.find({age : {$lt :200, $gt : 100}}) 
数组内 : db.products.find({ category: { $in: ["100", "200"] } })
数组外 : db.products.find({ category: { $nin: ["100", "200"] } })
大于等于 : db.col.find({age : {$gte : 150}})
小于等于 : db.col.find({age : {$lte : 150}})
等于 : db.col.find({age : {$eq : 150}})
不等于 : db.col.find({age : {$ne : 150}})


// Java 写法========
Bson bson = Filters.eq("username", "XDJHD20230517173938");

简单筛选

java 复制代码
// 去重
db.users.distinct("username")

分页和排序

java 复制代码
// 分页查询
db.users.find().sort({"username":1}).limit(2).skip(2)

// 排序查询
db.col.find({},{"title":1,_id:0}).sort({"likes":-1})   

// Java 写法========
Bson sortBs = Sorts.descending("createTime");
mongoTemplate.getCollection(COLLECTION).find(bson).limit(10).skip(1).sort(sortBs);

2.2 高级查询

AND 语句

java 复制代码
db.users.find({"$and":[{"username":"gang"},{"age":18}]},{"username":0,"age":
0})

// Java 写法========
Bson bson = Filters.and(
        Filters.eq("fieldA", "A"),
        Filters.eq("fieldB", "B")
);

OR 语句

java 复制代码
db.users.find( { $or: [{"year" : 1989}, {"username" :"gang"}] } )

// Java 写法============
Bson bson = Filters.and(
        Filters.or("fieldA", "A"),
        Filters.or("fieldB", "B")
);


// 稍微复杂点的合并查询
Bson bsonOr = Filters.or(
        Filters.eq("fieldA", "A"),
        Filters.eq("fieldB", "B")
);

Bson bsonAnd = Filters.and(
        bsonOr,
        Filters.eq("fieldC", "C"),
        Filters.eq("fieldD", "D")
);

模糊正则匹配

java 复制代码
// 使用正则查询
db.users.find({ "fieldA": /.*230517.*/i }).limit(10).skip(0)
db.users.find( { "username" : /^B/} )

// Java 写法============
Bson bsonAnd = Filters.regex("fieldA", "230517");
Bson bsonAnd = Filters.regex("fieldA", "^TEST\d*0517
Bson bsonAnd = Filters.regex("planCode", ".*230517.*");

PS :不管是原生语法还是Java写法,都可以通过正则表达式实现一定的模糊查询

- 但是切记!!模糊有风险,在没有命中主数据体的情况下,可能会把数据库跑崩!!

2.3 增删改操作

文档的插入

java 复制代码
db.products.insertOne( { item: "card", qty: 15 } );

db.products.insertMany( [ { _id: 10, item: "large box",
qty: 20 }, { _id: 11, item: "smallbox", qty: 55 }, { _id: 12, item: "medium box", qty: 30 }
] );

db.collection.insert

2.4 数据库管理

集合的创建

java 复制代码
// 创建一个集合
db.createCollection("runoob")
    
// 创建指定大小的集合 (size : 空间大小 , max : 文档个数 )
db.createCollection("mycol", { capped : true, autoIndexId : true, size : 6142800, max : 10000 } )    

// 删除集合 mycoll
db.mycoll.drop()

三. 高级用法

3.1 聚合查询

聚合查询主要是通过 $group语法根据指定的字段进行分组,并使用$sum$avg$min$max等操作符进行计算。

java 复制代码
// group 查询语法
{
    $group: {
        _id: <expression>, // 分组条件,通常是一个字段或表达式
        <field1>: { <accumulator1>: <expression1> }, // 聚合操作1
        <field2>: { <accumulator2>: <expression2> }, // 聚合操作2
        ...
    }
}

// 参数含义
- _id : 指定用于分组的条件,通常是一个字段的名称或表达式
- field : 要进行聚合操作的字段
- accumulator  : 聚合函数
- expression :聚合操作函数的参数,通常是一个字段名称或表达式,指定要进行聚合操作的字段或计算条件

accumulator 语法 :

  • $sum:计算指定字段的总和。例如,计算销售总额或数量总和
  • $avg:计算指定字段的平均值。例如,计算平均销售价格或平均评分
  • $max:找到指定字段的最大值。例如,找到最高温度记录
  • $min:找到指定字段的最小值。例如,找到最低库存量
  • $first:返回分组内第一个文档的指定字段的值
  • $last:返回分组内最后一个文档的指定字段的值
  • $push:将匹配文档的指定字段值添加到数组中
  • $addToSet:将匹配文档的指定字段值添加到一个集合中,去重复

使用案例 - expression 表达式的作用

expression 的存在让聚合查询存在了更多的可能性 , 总体来说有2种处理方式 :

java 复制代码
// 统计分组的文档数量 (按照 type 进行分组)
db.user.aggregate([
    {
        $group: {
            _id: "$type",  
            count: { $sum: 1 } 
        }
    }
]);


// 同时进行多个统计
db.user.aggregate([
    {
        $group: {
            _id: "$type",
            totalAge: { $sum: "$age" },       // 计算总和
            avgAge: { $avg: "$age" }          // 计算平均值
        }
    }
]);


// 条件表达式查询 (获取年龄大于50的总数)
db.user.aggregate([
    {
        $group: {
            _id: "$type",
            highSalesCount: {
                $sum: { $cond: { if: { $gte: ["$age", 50] }, then: 1, else: 0 } }
            }
        }
    }
]);

3.2 其他常用函数用法

java 复制代码
// 按照类型查询 : (查询包含Double类型的数据)
db.collection.find({ field: { $type: 1 } })
> 类型 : https://www.mongodb.com/docs/manual/reference/operator/query/type/#mongodb-query-op.-type

// all 数组查询
- 查询包含 abc 和 edf 2个名字的所有文档
db.user.find({ username: { $all: ["abc", "edf"] } })

// 查询包含 exactly 3 个标签的文章
db.articles.find({ tags: { $size: 3 } })

// 取模查询 - 查询所有余数为 0 的偶数文档
db.numbers.find({ value: { $mod: [2, 0] } })

// 正则表达式匹配 - 以 A开头的文档
db.collection.find({ name: { $regex: /^A/ } })

四. Java 用法

所有的 DB 库基本上都能通过实现对应的 Repository 来实现对 DB 实例的调用 ,使用方式极其简单 :

java 复制代码
@Repository
public interface SelectUserDas extends MongoRepository<UserDto, Long> {
    /**
     * 通过 userCode 进行删除
     */
    int deleteByCode(String userCode);
}

使用的时候基于 MongoRepository 能完成80%的功能,这一块文档很多,就不看了。我们要弄清除的是那剩下的20%

BSON 查询语法

java 复制代码
// 构建 BSON 查询语句
Bson sortBs = Sorts.descending("createTime"); Bson bson = Filters.eq("userCode", "DemoTest"); 

// find 中传入查询语句
FindIterable<Document> collect = mongoTemplate.getCollection(COLLECTION).find(bson).limit(10).skip(1).sort(sortBs);

Spring 使用过程中还是基于 Repository 的 Example 语法 :

java 复制代码
<S extends T> Page<S> findAll(Example<S> var1, Pageable var2);

// 使用方式
ExampleMatcher matcher = ExampleMatcher.matching()
    .withMatcher("username", ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase())
    .withMatcher("usercode", ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase());
Example<UserDo> example = Example.of(selectDto);
Sort sort = Sort.by(Sort.Direction.DESC, "createTime");
Pageable pageable = PageRequest.of(
pageDto.getPageNum() - NumberConstant.CONSTANT_1, pageDto.getPageSize(), sort);
Page<UserDo> userPageDto = selectionResultDas.findAll(example, pageable);

聚合查询

java 复制代码
@Resource
private MongoTemplate mongoTemplate;

@GetMapping("get")
public String agg() {
    // 定义聚合操作:按产品名称分组,并计算总销售额和平均销售金额
    GroupOperation groupOperation = Aggregation.group("type")
            .sum("age").as("totalAge")
            .avg("age").as("avgAge");

    // 构建聚合查询
    TypedAggregation<User> aggregation = Aggregation.newAggregation(User.class, groupOperation);

    // 执行聚合查询
    AggregationResults<JSONObject> result = mongoTemplate.aggregate(aggregation, JSONObject.class);

    // 获取聚合结果
    List<JSONObject> productSalesStatsList = result.getMappedResults();


    log.info("------> {} <-------", productSalesStatsList);
    return "sccuess";
}

这种方式基本上能解决99的问题,更复杂的可以看之前的一篇文章 juejin.cn/post/725325... ,里面详细说明了 MongoDB Client 的配置和使用方式。

总结

东西不多,简单记下。

相关推荐
皮皮林5511 小时前
IDEA 源码阅读利器,你居然还不会?
java·intellij idea
你的人类朋友1 小时前
什么是OpenSSL
后端·安全·程序员
bobz9651 小时前
mcp 直接操作浏览器
后端
前端小张同学4 小时前
服务器部署 gitlab 占用空间太大怎么办,优化思路。
后端
databook4 小时前
Manim实现闪光轨迹特效
后端·python·动效
武子康5 小时前
大数据-98 Spark 从 DStream 到 Structured Streaming:Spark 实时计算的演进
大数据·后端·spark
该用户已不存在5 小时前
6个值得收藏的.NET ORM 框架
前端·后端·.net
文心快码BaiduComate5 小时前
文心快码入选2025服贸会“数智影响力”先锋案例
前端·后端·程序员
neoooo5 小时前
🌐 Cloudflare Tunnel vs ZeroTier:两个世界的内网穿透哲学
后端
卡尔特斯5 小时前
Android Kotlin 项目代理配置【详细步骤(可选)】
android·java·kotlin