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 的配置和使用方式。

总结

东西不多,简单记下。

相关推荐
逊嘘7 分钟前
【Java语言】抽象类与接口
java·开发语言·jvm
morris13114 分钟前
【SpringBoot】Xss的常见攻击方式与防御手段
java·spring boot·xss·csp
monkey_meng31 分钟前
【Rust中的迭代器】
开发语言·后端·rust
余衫马34 分钟前
Rust-Trait 特征编程
开发语言·后端·rust
monkey_meng37 分钟前
【Rust中多线程同步机制】
开发语言·redis·后端·rust
七星静香38 分钟前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
Jacob程序员39 分钟前
java导出word文件(手绘)
java·开发语言·word
ZHOUPUYU40 分钟前
IntelliJ IDEA超详细下载安装教程(附安装包)
java·ide·intellij-idea
stewie643 分钟前
在IDEA中使用Git
java·git
Elaine2023911 小时前
06 网络编程基础
java·网络