Skip to main content

入门 《MongoDB权威指南》

· 预计阅读时间 8 min
小雨

本书从浅入深地介绍了MongoDB,是初学者非常全面的学习指南。

image-20220125000652822

二、第一部分 入门

1. 简介

MongoDB是面向文档的数据库,他的优势在于

  • 易于使用
  • 易于扩展
  • 功能丰富
    • 索引
    • 聚合
    • 特殊的集合和索引类型
    • 文件存储
  • 性能卓越

2.基本概念

以下是一些基本概念,通过这些概念可以对MongoDB有初步认识。

  • 文档相当于关系型数据库的行
  • 集合相当于关系型数据库的表
  • 一个MongoDB可以拥有多个独立的数据库
  • 每个文档都有唯一的键 _id
  • mongo shell 对MongoDB的实例管理和查询提供了内置操作

3.数据类型

MongoDB的文档被认为是类似JSON存储,以下是常见的数据类型

  • null
  • 布尔类型 true false
  • 数值类型 默认是64位的浮点型,还可以是NumberIne("3") 或者 NumberLong("3")
  • 字符串类型
  • 日期类型 new Date()
  • 正则表达式
  • 数组
  • 内嵌文档
  • Object ID
  • 二进制数据
  • 代码

4.插入数据

MongoDB支持单行插入insertOne,和多行插入insertMany

> db.t1.insertOne({"name":"xiaoyuqingnian"})
{
"acknowledged" : true,
"insertedId" : ObjectId("61ed6e4a6e4687eeb69f4487")
}
> db.t1.insertMany([{"name":"xiaoyuqingnian"},{"name":"xiaoyuqingnian2"}])
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("61ed6ef46e4687eeb69f4488"),
ObjectId("61ed6ef46e4687eeb69f4489")
]
}
  • MongoDB能够接收的最大消息长度是48MB,如果超过48MB,多数驱动程序会拆分成多个48MB的请求。
  • 所有文档的大小不能超过16MB

5.删除数据

deleteOne会删除符合条件的第一条数据,deleteMany则会删除符合条件的全部数据。

> db.t1.deleteOne({ "_id": ObjectId("61ed6e4a6e4687eeb69f4487")})
{ "acknowledged" : true, "deletedCount" : 1 }
> db.t1.insertMany([{"name":"xiaoyuqingnian","type":"a"},{"name":"xiaoyuqingnian2","type":"a"}])
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("61ed730c6e4687eeb69f448a"),
ObjectId("61ed730c6e4687eeb69f448b")
]
}
> db.t1.find()
{ "_id" : ObjectId("61ed6ef46e4687eeb69f4488"), "name" : "xiaoyuqingnian" }
{ "_id" : ObjectId("61ed6ef46e4687eeb69f4489"), "name" : "xiaoyuqingnian2" }
{ "_id" : ObjectId("61ed730c6e4687eeb69f448a"), "name" : "xiaoyuqingnian", "type" : "a" }
{ "_id" : ObjectId("61ed730c6e4687eeb69f448b"), "name" : "xiaoyuqingnian2", "type" : "a" }

> db.t1.deleteMany({ "type":"a"})
{ "acknowledged" : true, "deletedCount" : 2 }
> db.t1.find()
{ "_id" : ObjectId("61ed6ef46e4687eeb69f4488"), "name" : "xiaoyuqingnian" }
{ "_id" : ObjectId("61ed6ef46e4687eeb69f4489"), "name" : "xiaoyuqingnian2" }

如果不带条件则会删除整个集合。

> db.t1.deleteMany({})
{ "acknowledged" : true, "deletedCount" : 2 }

推荐删除集合的方式是drop()

6.更新文档

更新文档有三种

  • updateOne
  • updateMany
  • replaceOne

replaceOne注意只会匹配第一条数据,在有多条符合条件的记录时需要注意

> db.t1.replaceOne({"name":"xiaoyuqingnian"},{"name":"xiaoyuxiaoyu"})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.t1.find()
{ "_id" : ObjectId("61edf1586e4687eeb69f448c"), "name" : "xiaoyuxiaoyu" }
{ "_id" : ObjectId("61edf1586e4687eeb69f448d"), "name" : "xiaoyuqingnian2", "type" : "a" }
{ "_id" : ObjectId("61edf15a6e4687eeb69f448e"), "name" : "xiaoyuqingnian", "type" : "a" }
{ "_id" : ObjectId("61edf15a6e4687eeb69f448f"), "name" : "xiaoyuqingnian2", "type" : "a" }
{ "_id" : ObjectId("61edf15b6e4687eeb69f4490"), "name" : "xiaoyuqingnian", "type" : "a" }
{ "_id" : ObjectId("61edf15b6e4687eeb69f4491"), "name" : "xiaoyuqingnian2", "type" : "a" }
{ "_id" : ObjectId("61edf15c6e4687eeb69f4492"), "name" : "xiaoyuqingnian", "type" : "a" }
{ "_id" : ObjectId("61edf15c6e4687eeb69f4493"), "name" : "xiaoyuqingnian2", "type" : "a" }
{ "_id" : ObjectId("61edf15d6e4687eeb69f4494"), "name" : "xiaoyuqingnian", "type" : "a" }
{ "_id" : ObjectId("61edf15d6e4687eeb69f4495"), "name" : "xiaoyuqingnian2", "type" : "a" }
{ "_id" : ObjectId("61edf15d6e4687eeb69f4496"), "name" : "xiaoyuqingnian", "type" : "a" }
{ "_id" : ObjectId("61edf15d6e4687eeb69f4497"), "name" : "xiaoyuqingnian2", "type" : "a" }
{ "_id" : ObjectId("61edf15e6e4687eeb69f4498"), "name" : "xiaoyuqingnian", "type" : "a" }
{ "_id" : ObjectId("61edf15e6e4687eeb69f4499"), "name" : "xiaoyuqingnian2", "type" : "a" }
{ "_id" : ObjectId("61edf1636e4687eeb69f449a"), "name" : "xiaoyuqingnian", "type" : "a" }
{ "_id" : ObjectId("61edf1636e4687eeb69f449b"), "name" : "xiaoyuqingnian2", "type" : "c" }
{ "_id" : ObjectId("61edf1666e4687eeb69f449c"), "name" : "xiaoyuqingnian", "type" : "a" }
{ "_id" : ObjectId("61edf1666e4687eeb69f449d"), "name" : "xiaoyuqingnian2", "type" : "d" }
> db.t1.replaceOne({"name":"xiaoyuqingnian"},{"name":"xiaoyuxiaoyu"})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.t1.find()
{ "_id" : ObjectId("61edf1586e4687eeb69f448c"), "name" : "xiaoyuxiaoyu" }
{ "_id" : ObjectId("61edf1586e4687eeb69f448d"), "name" : "xiaoyuqingnian2", "type" : "a" }
{ "_id" : ObjectId("61edf15a6e4687eeb69f448e"), "name" : "xiaoyuxiaoyu" }
{ "_id" : ObjectId("61edf15a6e4687eeb69f448f"), "name" : "xiaoyuqingnian2", "type" : "a" }
{ "_id" : ObjectId("61edf15b6e4687eeb69f4490"), "name" : "xiaoyuqingnian", "type" : "a" }
{ "_id" : ObjectId("61edf15b6e4687eeb69f4491"), "name" : "xiaoyuqingnian2", "type" : "a" }
{ "_id" : ObjectId("61edf15c6e4687eeb69f4492"), "name" : "xiaoyuqingnian", "type" : "a" }
{ "_id" : ObjectId("61edf15c6e4687eeb69f4493"), "name" : "xiaoyuqingnian2", "type" : "a" }
{ "_id" : ObjectId("61edf15d6e4687eeb69f4494"), "name" : "xiaoyuqingnian", "type" : "a" }
{ "_id" : ObjectId("61edf15d6e4687eeb69f4495"), "name" : "xiaoyuqingnian2", "type" : "a" }
{ "_id" : ObjectId("61edf15d6e4687eeb69f4496"), "name" : "xiaoyuqingnian", "type" : "a" }
{ "_id" : ObjectId("61edf15d6e4687eeb69f4497"), "name" : "xiaoyuqingnian2", "type" : "a" }
{ "_id" : ObjectId("61edf15e6e4687eeb69f4498"), "name" : "xiaoyuqingnian", "type" : "a" }
{ "_id" : ObjectId("61edf15e6e4687eeb69f4499"), "name" : "xiaoyuqingnian2", "type" : "a" }
{ "_id" : ObjectId("61edf1636e4687eeb69f449a"), "name" : "xiaoyuqingnian", "type" : "a" }
{ "_id" : ObjectId("61edf1636e4687eeb69f449b"), "name" : "xiaoyuqingnian2", "type" : "c" }
{ "_id" : ObjectId("61edf1666e4687eeb69f449c"), "name" : "xiaoyuqingnian", "type" : "a" }
{ "_id" : ObjectId("61edf1666e4687eeb69f449d"), "name" : "xiaoyuqingnian2", "type" : "d" }

更新运算符用来对文档进行部分更新,比如数据增减、数组元素的增删。

> db.t1.insertOne({"name":"xiaoyu","blogCount":"1"})
{
"acknowledged" : true,
"insertedId" : ObjectId("61eeb3226e4687eeb69f449e")
}

> db.t1.insertOne({"name":"xiaoyuqingnian","blogCount":1})
{
"acknowledged" : true,
"insertedId" : ObjectId("61eeb3f26e4687eeb69f449f")
}
> db.t1.updateOne({"_id":ObjectId("61eeb3f26e4687eeb69f449f")},{$inc:{"blogCount":1}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

{ "_id" : ObjectId("61eeb3f26e4687eeb69f449f"), "name" : "xiaoyuqingnian", "blogCount" : 2 }

涉及到的用法有

  • $inc 增加数字
  • $set 设置
  • $push将元素添加到数组末尾
  • $ne $addToSet 不存在时才添加,避免重复添加
  • $pop从数组头部或者尾部删除元素
  • $pull删除符合条件匹配元素
  • upsert如果匹配不到就新增文档

返回被更新的文档,有三种集合方法,分别完成了删除、替换、更新等方法

  • findOneAndDelete
  • findOneAndReplace
  • findOneAndUpdate

7.查询文档

注意的是,查询的值必须是常量、

find() 不带条件就是查询全部结果,带条件就是查询匹配的结果,我们可以通过下面的比较运算符做条件比较

  • $lt 小于 <
  • $lte 小于等于 <=
  • $gt 大于 >
  • $gte 大于等于 >=
  • $ne 不等于 !=
> db.t1.find({ "blogCount" : { "$lt": 10 }})
{ "_id" : ObjectId("61eeb3f26e4687eeb69f449f"), "name" : "xiaoyuqingnian", "blogCount" : 2 }

OR查询支持两种,$in支持查询多个键值,$or可以查询多个匹配值。

$not可以和任何条件结合,表示不匹配。

$regex可以匹配正则表达式。

数组查询

  • $all查询全部元素
  • $size查询特定数组长度
  • $slice返回特定长度的子集

分页和sql类似,使用limitskipsort进行限定结果。

> db.t1.find().skip(1).limit(2).sort({"name":1})
{ "_id" : ObjectId("61eec9cf6e4687eeb69f44a0"), "name" : "xiaoyu2", "blogCount" : "10" }
{ "_id" : ObjectId("61eec9d86e4687eeb69f44a1"), "name" : "xiaoyu3", "blogCount" : "15" }

三、总结

本书的第一部分从基础入手,介绍了Mongo的特点、数据类型、增删改查的语法。

值得留意的是,本文的语言十分诙谐,在描述插入文档时,提到了所有文档大小必须小于16MB,而《战争与和平》整部著作也只有3.14MB。

这部分留下的坑,后续单独补上

  • 数组的插入完整案例
  • 数组的查询完整案例
  • 游标的使用和理解