当前位置: 首页 > news >正文

Mongo的增删改查

一、MongoDB 是什么?

MongoDB 是一个开源的、面向文档的 NoSQL 数据库,由 C++ 编写,旨在为 Web 应用提供可扩展的高性能数据存储解决方案。

  • 核心特点
    • 存储的是 BSON(Binary JSON) 格式的文档,结构灵活。
    • 支持动态 schema,无需提前定义表结构。
    • 高性能、高可用(副本集)、可水平扩展(分片集群)。
    • 支持丰富的查询语言,包括范围查询、正则表达式、聚合管道等。
  • ·

二、MongoDB 的数据类型(常用)

MongoDB 支持丰富的数据类型,比 JSON 更强大:

类型

说明

String

字符串

Number

整数、浮点数(int

, long

, double

, decimal

Boolean

true / false

Object

嵌套文档

Array

数组,可包含多个值或嵌套文档

Date

日期时间(毫秒级)

ObjectId

12字节的唯一标识符,常用于 _id

主键

Null

表示空值

Binary Data

存储二进制数据

Timestamp

用于内部操作的时间戳

Regex

正则表达式

✅ MongoDB 数据类型与 Java 类型对照表

MongoDB 类型

说明

示例

Java 常用类型(Spring Data MongoDB)

String

UTF-8 编码的字符串,最常用类型

"杭州"

, "张三"

java.lang.String

Number

数值类型,根据值自动判断:<br>• int

/ long

(整数)<br>• double

(浮点数)<br>• decimal

(高精度)

30

, 3.14

, NumberDecimal("10.01")

int

/ Integer

<br>• long

/ Long

<br>• double

/ Double

<br>• java.math.BigDecimal

(高精度金额)

Boolean

布尔值,表示真或假

true

, false

boolean

/ Boolean

Object

嵌套文档(子文档),用于结构化数据

{ "city": "杭州", "district": "余杭区" }

自定义 Java 类(如 Address

),通过 @Document

或普通 POJO 映射

Array

数组,可包含字符串、数字、对象等,支持嵌套

["reading", "coding"]

, [{"k":"a"},{"k":"b"}]

java.util.List<T>

(最常用)<br>或 T[]

(数组)<br>例如:List<String>

, List<OrderItem>

Date

日期时间类型,存储 UTC 时间戳(毫秒级精度)

ISODate("2025-01-01T00:00:00Z")

java.util.Date

(传统)<br>• java.time.Instant

(推荐)<br>• java.time.LocalDateTime

(需注意时区处理)<br>• java.time.ZonedDateTime

ObjectId

12字节的唯一标识符,MongoDB 默认 _id

主键类型,由时间戳 + 机器信息生成

ObjectId("507f1f77bcf86cd799439011")

org.bson.types.ObjectId

(BSON 库)<br>• String

(存储为十六进制字符串,便于传输)<br>⚠️ 建议:Java 实体中用 String

,数据库用 ObjectId

,通过 Converter 转换

Null

表示空值或字段不存在

"nickname": null

null

(任何引用类型)

Binary Data

存储二进制数据,如图片、文件、加密数据等

BinData(0, "SGVsbG8=")

byte[]

(最常用)<br>或 java.nio.ByteBuffer

Timestamp

用于 MongoDB 内部操作的时间戳(如 oplog),不推荐用于业务时间

Timestamp(1620000000, 1)

org.bson.types.BSONTimestamp

(极少用于业务开发)

Regex

正则表达式对象,用于模式匹配查询

/^张.*/i

java.util.regex.Pattern

(Java 中表示正则)

示例文档:

{// ObjectId 类型:12字节的唯一标识符,MongoDB 默认主键// 由时间戳 + 机器ID + 进程ID + 计数器生成,全局唯一,避免冲突// 在 Java 中通常映射为 String 或 ObjectId 类型"_id": ObjectId("507f1f77bcf86cd799439011"),// String 类型:UTF-8 编码的字符串// 存储姓名、昵称、标题等文本信息// 在 Java 中对应 String"name": "张三",// NumberInt 类型:32位整数(默认)// 如果数值较大,建议使用 NumberLong(64位)// 在 Java 中对应 int / Integer 或 long / Long"age": 30,// Array 类型:有序列表,可包含相同或不同类型的元素(推荐同类型)// 这里是字符串数组,存储用户的兴趣爱好// 支持 $push, $addToSet, $pull 等数组操作// 在 Java 中通常映射为 List<String>"hobbies": ["reading", "coding"],// Embedded Document(嵌套文档)类型:文档中包含子文档// 用于结构化数据,如地址、配置、用户详情等// 支持通过 "address.city" 这样的点号语法查询// 在 Java 中通常映射为一个独立的类(如 Address.class)"address": {"city": "杭州",        // String:城市"district": "余杭区"   // String:区县},// Date 类型:ISODate,存储 UTC 时间戳(毫秒级精度)// MongoDB 内部以 64 位整数存储毫秒数,支持时区转换// 在 Java 中对应 java.util.Date 或 java.time.Instant / LocalDateTime// 阿里规范:所有时间字段统一用 UTC 存储,前端展示时转换为本地时间"createdAt": ISODate("2025-01-01T00:00:00Z")
}

三、MongoDB vs Redis vs MySQL

既要读写又要事务:mysql

只要读写速度,不要事务,数据量小:redis

既要读写,数据量又大:mongoDb

对比维度

MongoDB

Redis

MySQL

数据模型

文档(BSON)

键值对(支持 String, Hash, List 等)

关系型表(行和列)

查询能力

强:支持复杂查询、索引、聚合

弱:主要基于 key,复杂查询需应用层处理

强:SQL,支持 JOIN、事务等

性能

高读写性能,适合海量数据

极高(内存数据库),适合缓存

中等,受磁盘和锁机制影响

持久化

支持(WAL 日志 + 定期刷盘)

支持(RDB/AOF)

支持(InnoDB)

扩展性

易水平扩展(Sharding)

支持集群,但复杂

难水平扩展(需中间件如 MyCAT)

事务支持

支持多文档 ACID 事务(4.0+)

支持简单事务(MULTI/EXEC)

强事务支持(ACID)

典型用途

内容管理、日志、用户画像

缓存、会话存储、排行榜

核心交易系统、财务系统

MongoDB 的优势总结

  • 比 MySQL 更灵活,适合 schema 频繁变更的场景。
  • 比 Redis 存储容量更大,支持复杂查询,适合持久化存储。
  • 天然支持嵌套结构,减少 JOIN,适合 JSON 类数据。

四、MongoDB 的典型使用场景

  1. 内容管理系统(CMS)
    • 文章、页面结构多变,适合用文档存储。
  1. 用户行为日志 & 埋点数据
    • 数据量大、写入频繁、schema 不固定。
  1. 商品详情页(阿里商品中心常用)
    • 商品属性复杂、SKU 多,用嵌套文档天然匹配。
  1. 实时分析系统
    • 聚合管道(Aggregation Pipeline)支持复杂统计。
  1. 物联网(IoT)数据
    • 设备上报数据结构多样,写入频率高。
  1. 微服务架构中的独立数据存储
    • 每个服务拥有自己的数据库,避免耦合。

五、MongoDB 增删改查(CRUD)操作(Shell 语法)

假设集合名为 users

1. 插入(insert)
// 插入单条
db.users.insertOne({name: "李四",age: 25,city: "北京"
})// 插入多条
db.users.insertMany([{ name: "王五", age: 28, city: "上海" },{ name: "赵六", age: 32, city: "深圳" }
])
2. 查询(find)

查询 ObjectId 类型字段时,必须用 ObjectId("...") 包裹,并加引号。

查询字符串类型字段时,直接用引号包裹字符串


// 查询所有
db.users.find()// id查询
//查询 ObjectId 类型字段时,必须用 ObjectId("...") 包裹,并加引号。
db.crm_company_extensible.findOne({_id: {$eq: ObjectId("68a4279a9e2a6581afa4838d")}});// 条件查询
db.users.find({ age: { $gt: 26 } }) 查询年龄大于26岁的数据
//查询name=xx的数据 下面两种写法等价
db.crm_company_extensible.find({name:{$eq:"成都京东楠苑贸易有限公司"}}); 
db.crm_company_extensible.find({name:"成都京东楠苑贸易有限公司"});// 投影(只返回某些字段)   第二个{},就是你要返回的字段,写1代表要,0代表不要
db.users.find({ city: "北京" }, { name: 1, age: 1, _id: 0 })
db.crm_company_extensible.find({name:"成都京东楠苑贸易有限公司"},{name:1,mainStaffInfo:1});
解释:
第一个 {}:查询条件(filter)—— 找出 city 是 "北京" 的文档。
第二个 {}:投影(projection)—— 控制返回哪些字段:
1 表示包含该字段
0 表示排除该字段
_id: 0 表示不返回 _id 字段(默认总是返回)// 排序 + 分页
db.users.find().sort({ age: -1 }).limit(2).skip(1)
解释:
.sort({ age: -1 }):按 age 降序排列(1 为升序)
.limit(2):最多返回 2 条
.skip(1):跳过前 1 条(常用于分页)skip + limit 在大数据量下性能较差,建议结合 游标(cursor)或范围查询 优化
// 更优方式:用 age > lastSeenAge 实现“下一页”
db.users.find({ age: { $lt: 30 } }).sort({ age: -1 }).limit(10)// 模糊查询
db.users.find({ name: /李/ })
db.crm_company_extensible.find({ name: /成/ })
{ name: /^李/ }     // 以“李”开头
{ name: /李$/ }     // 以“李”结尾
{ name: /li/i }     // 忽略大小写(i 标志)// 嵌套查询
db.users.find({ "address.city": "杭州" })
db.crm_company_extensible.find({ "basicInfo.approvedTime": "2024-04-30" }) //

嵌套查询


db.users.find({ "address.city": "杭州" })
  • 查询 address 是一个嵌套文档,其中 city 字段等于 "杭州" 的记录。
  • 使用 点号(dot notation) 访问嵌套字段。

✅ 示例文档:

{"name": "张三","address": {"city": "杭州","district": "余杭区"}
}

分页:skip + limit 在大数据量下性能较差,建议结合 游标(cursor)或范围查询 优化

嵌套查询

3. 更新(Update)

操作符,看下面,这个比mysql复杂一点,可以直接介于操作符加减等

// 更新单条(默认只更新匹配的第一条)
db.users.updateOne({ name: "李四" }, //更新条件{ $set: { age: 26, city: "天津" } } //更新age为26,城市为天津
)
db.crm_company_extensible.updateOne({name:"企查查科技股份有限公司"},{$set:{name:"企查查科技股份有限公司1"}})// 更新多条
db.users.updateMany({ age: { $lt: 30 } },{ $inc: { age: 1 } }  // 年龄 +1
)
db.crm_company_extensible.updateMany({name:"成都京东楠苑贸易有限公司"},{$set:{name:"成都京东楠苑贸易有限公司1"}})// 替换整个文档
db.users.replaceOne({ name: "赵六" },{ name: "钱七", age: 33, city: "广州" }
)
4. 删除(Delete)
// 删除单条
db.users.deleteOne({ name: "钱七" })
db.crm_company_extensible.deleteOne({name:"成都京东楠苑贸易有限公司1"})// 删除多条
db.users.deleteMany({ city: "深圳" })// 删除所有(慎用)
db.users.deleteMany({})

1. acknowledged

  • 类型:布尔值 (truefalse)
  • 含义
    • true 表示服务器已经确认了你的删除请求,并且该操作已经被记录到日志中。
    • false 表示服务器没有确认你的删除请求,可能是因为网络问题、超时或其他错误。

2. deletedCount

  • 类型:整数
  • 含义
    • 这个字段表示实际被删除的文档数量。
    • 如果你执行了一个删除操作,但没有任何文档匹配你的查询条件,那么 deletedCount 将会是 0
    • 如果有多个文档匹配你的查询条件并且都被成功删除,那么 deletedCount 将会是你所删除的文档的数量。

六、排序

  • 1:升序(从小到大)
  • -1:降序(从大到小)
按年龄升序排列
db.users.find().sort({ age: 1 })按时间倒序(最新在前)
db.users.find().sort({ createdAt: -1 })多字段排序 —— 先按年龄升序,再按分数降序
db.users.find().sort({ age: 1, score: -1 })结合查询条件 + 排序 + 分页(真实生产写法)
// 查询状态为 "active" 的用户,按分数降序,取前 10 条
db.users.find({ status: "active" }).sort({ score: -1 }).limit(10)

七、操作符

在 MongoDB 中,所有以 $ 开头的关键词都是“操作符”,用于表达查询条件、更新操作、聚合逻辑等。

常见 $ 操作符分类:

1. 查询操作符(Query Operators)

操作符

说明

示例

$eq

等于

{ age: { $eq: 25 } }

$gt

大于

{ age: { $gt: 18 } }

$gte

大于等于

{ age: { $gte: 18 } }

$lt

小于

{ age: { $lt: 60 } }

$in

在集合中

{ city: { $in: ["北京", "上海"] } }

$nin

不在集合中

{ city: { $nin: ["深圳"] } }

$exists

字段是否存在

{ email: { $exists: true } }

$regex

正则匹配

{ name: { $regex: /李/ } }

✅ 上面的 /李/ 是简写,等价于 { name: { $regex: "李" } }

2. 更新操作符(Update Operators)

操作符

说明

示例

$set

设置字段值

{ $set: { status: "active" } }

$unset

删除字段

{ $unset: { temp: "" } }

$inc

数值增加

{ $inc: { age: 1 } }

$push

向数组添加元素

{ $push: { tags: "new" } }

$pull

从数组删除元素

{ $pull: { tags: "old" } }

$addToSet

向数组添加(去重)

{ $addToSet: { tags: "java" } }

🔁 你之前看到的:

{ $set: { age: 26 } }    // 修改字段
{ $inc: { age: 1 } }      // 年龄 +1
3. 逻辑操作符

操作符

说明

$and

$or

$not

$nor

都不满足

示例:

db.users.find({$or: [{ age: { $lt: 18 } },{ city: "杭州" }]
})

补充:Java 中如何操作 MongoDB?

在阿里,我们通常使用 Spring Data MongoDBMongo Java Driver

// 示例:Spring Data MongoDB
@Repository
public interface UserRepository extends MongoRepository<User, String> {List<User> findByCity(String city);List<User> findByAgeGreaterThan(int age);
}

总结

  • MongoDB 是文档数据库,适合存储结构灵活、读写频繁的业务数据。
  • 相比 Redis:Mongo 更适合持久化和复杂查询;Redis 更适合高速缓存。
  • 相比 MySQL:Mongo 更易扩展、schema 自由;MySQL 更适合强一致性事务。
  • 使用场景:日志、内容、用户画像、商品详情等。
  • CRUD 操作 简洁直观,支持丰富查询语法。

文章转载自:

http://2W3NxL0G.ghxsn.cn
http://jyMgcINS.ghxsn.cn
http://uoJO1w5E.ghxsn.cn
http://B54Puqcu.ghxsn.cn
http://wnQZySdw.ghxsn.cn
http://HYpDa6KE.ghxsn.cn
http://lve5uROs.ghxsn.cn
http://0s1VdD4z.ghxsn.cn
http://wYJQdz90.ghxsn.cn
http://s4ZmF8fh.ghxsn.cn
http://pcz2iarB.ghxsn.cn
http://ZsqSw0zy.ghxsn.cn
http://aVnGs35R.ghxsn.cn
http://XhIVINcy.ghxsn.cn
http://P0FG8KMf.ghxsn.cn
http://gKbySaMN.ghxsn.cn
http://tmy748QM.ghxsn.cn
http://BGZ0bz8y.ghxsn.cn
http://JwoU5D9i.ghxsn.cn
http://6jpxjY14.ghxsn.cn
http://AujVZg67.ghxsn.cn
http://xYOI0xPu.ghxsn.cn
http://topI3tZZ.ghxsn.cn
http://DIOW1W8M.ghxsn.cn
http://DIdsnyRD.ghxsn.cn
http://MW2mtc7X.ghxsn.cn
http://eioTKzrO.ghxsn.cn
http://fKccIlZl.ghxsn.cn
http://O2oi2AFX.ghxsn.cn
http://WpjIRHe2.ghxsn.cn
http://www.dtcms.com/a/367427.html

相关文章:

  • 裸签、Attach、Detach及其验签方式
  • 「数据获取」中国科技统计年鉴(1991-2024)Excel
  • 无人机防风技术难点解析
  • 【Unity知识分享】Unity接入dll调用Window系统接口
  • 异地多活架构:从“机房炸了”到“用户无感”的逆袭之路
  • 【系统架构设计(16)】软件架构设计二:软件架构风格:构建系统的设计模式与选择指南
  • 树形组件,支持搜索展示,自定义展示,支持vue2,vue3,小程序等等
  • 去中心化投票系统开发教程
  • Eclipse 常用搜索功能汇总
  • go面试题-什么是用户态和内核态
  • C++语言编程规范-常量
  • windows线程注入
  • LeetCode 48 - 旋转图像算法详解(全网最优雅的Java算法
  • ResNet(残差网络)-彻底改变深度神经网络的训练方式
  • Docker多阶段构建Maven项目
  • 山姆·奥特曼 (Sam Altman) 分享提高工作效率的方法
  • 【赛题已出】2025高教社杯全国大学生数学建模竞赛ABCDE赛题已发布!
  • Git的强软硬回退(三)
  • 网络计算工具ipcalc详解
  • rabbitmq 入门知识点
  • C++ 中基类和派生类对象的赋值与转换
  • STM32F103_Bootloader程序开发15 - 从Keil到vscode + EIDE + GCC的迁移实践
  • 神马 M21 31T 矿机解析:性能、规格与市场应用
  • 解析 Quartz 报错:Table ‘test.QRTZ_LOCKS‘ doesn‘t exist 的解决方案
  • 【高等数学】第十一章 曲线积分与曲面积分——第二节 对坐标的曲线积分
  • 产品推荐|千眼狼宽光谱高速摄像机NEO系列
  • ECIES实现原理
  • Linux安装RTL8821CE无线网卡驱动
  • 下载及交叉编译libconfig
  • AutoLayout与Masonry:简化iOS布局