MongoDB学习笔记

MongoDB

什么是MongoDB

MongoDB是一个文档数据库(以 JSON 为数据模型),由C++语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案。

MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,数据格式是BSON,一种类似JSON的二进制形式的存储格式,简称Binary JSON ,和JSON一样支持内嵌的文档对象和数组对象,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。原则上 Oracle 和 MySQL 能做的事情,MongoDB 都能做(包括 ACID 事务)。


判断业务是否适合使用MongoDB

只要有一项需求满足就可以考虑使用MongoDB,匹配越多,选择MongoDB越合适。


安装MongoDB

Docker安装

  • 第一步: 创建数据目录和配置文件

    • 创建数据目录,直接将MongoDB镜像中的数据挂载到此目录
    shell 复制代码
       mkdir  /Users/cheng/mongo
       mkdir /Users/cheng/mongo/data
    • 创建配置文件mongod.conf
    shell 复制代码
    mkdir /Users/cheng/mongo/conf
    vim mongod.conf
    shell 复制代码
    # mongod.conf 配置文件  yml格式
    storage:
     dbPath: /data/db
    net:
     bindIp: 0.0.0.0
    port: 27017
    security:
     authorization: enabled
  • 第二步:搜索镜像并拉取

    • docker search mongo
    • docker pull mongo
  • 第三步: 启动镜像

    • docker run --name mongo1 -p 27017:27017 -v /Users/cheng/mango/data:/data/db \
      -v /Users/cheng/mango/conf/mongod.conf:/etc/mongo/mongod.conf -itd mongo --config /etc/mongo/mongod.conf --auth
  • 第四步: 进入mongosh

    • docker ps | grep mongo # 查询镜像id
    • docker exec -it 镜像id mongosh admin
    • 进入镜mongosh成功
  • 第五步:创建管理员

    shell 复制代码
    # 设置管理员用户名密码需要切换到admin库
    use admin  
    #创建管理员
    db.createUser({user:"root",pwd:"root",roles:[{role:"root",db:'admin'}]})
    # 登录
    db.auth({user:'root',pwd:'root'})
    # 查看当前数据库所有用户信息 
    show users 
    #显示可设置权限
    show roles 
    #显示所有用户
    db.system.users.find()
    • 常用权限

mongosh常用命令


增、删、改、查

创建数据集

db.createCollection('emp')

插入文档

MongoDB提供了以下方法将文档插入到集合中:

  • db.emp.insertOne() #插入单条
  • db.emp.insertMany() #插入多条
插入单条记录
shell 复制代码
	# 简单实例
	db.emp.insertOne({name:'test',age:22})  # 插入语句
	## 下方是返回结果
	{
	  acknowledged: true,
	  insertedId: ObjectId('66b8f4a06834104abef3f54e')
	}

	# insertOne支持设置writeConcern(写入确认选项)
	db.emp.insertOne(
	   { name: "test2", age: 35},
	   {
	      writeConcern: { w: "majority", j: true, wtimeout: 5000 }
	   }
	)

writeConcern 是 MongoDB 中用来控制写入确认的选项。以下是 writeConcern 参数的一些常见选项:

  • w:指定写入确认级别。如果指定为数字,则表示要等待写入操作完成的节点数。如果指定为 majority,则表示等待大多数节点完成写入操作。默认为 1,表示等待写入操作完成的节点数为 1。
  • j:表示写入操作是否要求持久化到磁盘。如果设置为 true,则表示写入操作必须持久化到磁盘后才返回成功。如果设置为 false,则表示写入操作可能在数据被持久化到磁盘之前返回成功。默认为 false。
  • wtimeout:表示等待写入操作完成的超时时间,单位为毫秒。如果超过指定的时间仍然没有返回确认信息,则返回错误。默认为 0,表示不设置超时时间
插入多条记录
js 复制代码
// 语法格式
db.collection.insertMany(
   [ <document 1> , <document 2>, ... ],
   {
      writeConcern: <document>,
      ordered: <boolean>      
   }
)
// writeConcern:写入确认选项,可选。
// ordered:指定是否按顺序写入,默认 true,按顺序写入。

查询文档

js 复制代码
//语法格式
db.collection.findOne(query, projection)  //查询第一个文档
db.collection.find(query, projection)
// query :可选,使用查询操作符指定查询条件
// projection :可选,使用投影操作符指定返回的键。
//查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
//投影时,_id为1的时候,其他字段必须是1;_id是0的时候,其他字段可以是0;
//如果没有_id字段约束,多个其他字段必须同为0或同为1。

//如果查询返回的条目数量较多,mongosh则会自动实现分批显示。
//默认情况下每次只显示20条,可以输入it命令读取下一批。


//正则表达式
//使用正则表达式查找name包含 te 字符串的
db.emp.find({name:{$regex:"te"}})
//或者
db.emp.find({name:/te/})

//分页
//skip用于指定跳过记录数,limit则用于限定返回结果数量。
//可以在执行find命令的同时指定skip、limit参数,以此实现分页的功能。
db.emp.find().skip(2).limit(3)
  • 条件转义

  • 处理分页问题 -- 巧分页

    • 数据量大的时候,应该避免使用skip/limit形式的分页。
    • 替代方案:使用查询条件+唯一排序条件;
    javascript 复制代码
    //例如: 
    //第一页:
    db.books.find({}).sort({_id: 1}).limit(10); 
    //第二页:
    db.books.find({_id: {$gt: <第一页最后一个_id>}}).sort({_id: 1}).limit(10); 
    //第三页:
    db.books.find({_id: {$gt: <第二页最后一个_id>}}).sort({_id: 1}).limit(10); 
  • 处理分页问题 -- 避免使用 count

    • 尽可能不要计算总页数,特别是数据量大和查询条件不能完整命中索引时。

      js 复制代码
      	// 考虑以下场景:假设集合总共有 1000w 条数据,在没有索引的情况下考虑以下查询:
      	db.coll.find({x: 100}).limit(50);
      	db.coll.count({x: 100}); 
    • 前者只需要遍历前 n 条,直到找到 50 条 x=100 的文档即可结束;

    • 后者需要遍历完 1000w 条找到所有符合要求的文档才能得到结果。 为了计算总页数而进行的 count() 往往是拖慢页面整体加载速度的原因

更新文档

MongoDB提供了以下方法来更新集合中的文档:

  • db.collection.updateOne ():即使多个文档可能与指定的筛选器匹配,也只会更新第一个匹配的文档。
  • db.collection.updateMany ():更新与指定筛选器匹配的所有文档。
更新操作符
更新单个文档'
js 复制代码
//语法
db.collection.updateOne(
   <filter>,
   <update>,
   {
     upsert: <boolean>,
     writeConcern: <document>,
     collation: <document>,
     arrayFilters: [ <filterdocument1>, ... ],
     hint:  <document|string>        // Available starting in MongoDB 4.2.1
   }
)

db.collection.updateOne()方法的参数含义如下:

  • <filter>:一个筛选器对象,用于指定要更新的文档。只有与筛选器对象匹配的第一个文档才会被更新。
  • <update>:一个更新操作对象,用于指定如何更新文档。可以使用一些操作符,例如 s e t 、 set、 set、inc、$unset等,以更新文档中的特定字段。
  • upsert:一个布尔值,用于指定如果找不到与筛选器匹配的文档时是否应插入一个新文档。如果upsert为true,则会插入一个新文档。默认值为false。
  • writeConcern:一个文档,用于指定写入操作的安全级别。可以指定写入操作需要到达的节点数或等待写入操作的时间。
  • collation:一个文档,用于指定用于查询的排序规则。例如,可以通过指定locale属性来指定语言环境,从而实现基于区域设置的排序。
  • arrayFilters:一个数组,用于指定要更新的数组元素。数组元素是通过使用更新操作符 [ ] 和 []和 []和来指定的。
  • hint:一个文档或字符串,用于指定查询使用的索引。该参数仅在MongoDB 4.2.1及以上版本中可用。
    注意,除了filter和update参数外,其他参数都是可选的。
更新多个文档

updateMany更新与集合的指定筛选器匹配的所有文档

js 复制代码
//例如
db.emp.updateMany({name:"test"},{$set:{publishedDate:new Date()}})
findAndModify

findAndModify兼容了查询和修改指定文档的功能,findAndModify只能更新单个文档

js 复制代码
//将某个文档的收藏数属性(favCount)加1
db.emp.findAndModify({
    query:{_id:ObjectId("6457a39c817728350ec83b9d")},
    update:{$inc:{favCount:1}}
})

默认情况下,findAndModify会返回修改前的"旧"数据。如果希望返回修改后的数据,则可以指定new选项

js 复制代码
db.books.findAndModify({
    query:{_id:ObjectId("6457a39c817728350ec83b9d")},
    update:{$inc:{favCount:1}},
    new: true   //返回修改后的数据
})

与findAndModify语义相近的命令如下:

  • findOneAndUpdate:更新单个文档并返回更新前(或更新后)的文档。
  • findOneAndReplace:替换单个文档并返回替换前(或替换后)的文档。

删除文档

deleteOne &deleteMany

官方推荐使用 deleteOne() 和 deleteMany() 方法删除文档,语法格式如下:

js 复制代码
db.emp.deleteOne ({ name:"test" })  //删除 name等于test 的一个文档
db.emp.deleteMany ({})  //删除集合下全部文档
db.emp.deleteMany ({ name:"test" })  //删除 name等于test 的全部文档

注意:remove、deleteMany命令需要对查询范围内的文档逐个删除,如果希望删除整个集合,则使用drop命令会更加高效

findOneAndDelete

deleteOne命令在删除文档后只会返回确认性的信息,如果希望获得被删除的文档,则可以使用findOneAndDelete命令

js 复制代码
db.emp.findOneAndDelete({name:"test"})

除了在结果中返回删除文档,findOneAndDelete命令还允许定义"删除的顺序",即按照指定顺序删除找到的第一个文档。利用这个特性,findOneAndDelete可以实现队列的先进先出。

js 复制代码
db.emp.findOneAndDelete({name:"test"},{sort:{favCount:1}})

批量操作

bulkwrite()方法提供了执行批量插入、更新和删除操作的能力。

bulkWrite()支持以下写操作:

  • insertOne
  • updateOne
  • updateMany
  • replaceOne
  • deleteOne
  • deleteMany

每个写操作都作为数组中的文档传递给bulkWrite()。

js 复制代码
db.pizzas.insertMany( [
   { _id: 0, type: "pepperoni", size: "small", price: 4 },
   { _id: 1, type: "cheese", size: "medium", price: 7 },
   { _id: 2, type: "vegan", size: "large", price: 8 }
] )

db.pizzas.bulkWrite( [
      { insertOne: { document: { _id: 3, type: "beef", size: "medium", price: 6 } } },
      { insertOne: { document: { _id: 4, type: "sausage", size: "large", price: 10 } } },
      { updateOne: {
         filter: { type: "cheese" },
         update: { $set: { price: 8 } }
      } },
      { deleteOne: { filter: { type: "pepperoni"} } },
      { replaceOne: {
         filter: { type: "vegan" },
         replacement: { type: "tofu", size: "small", price: 4 }
      } }
   ] )
相关推荐
马剑威(威哥爱编程)4 小时前
MongoDB面试专题33道解析
数据库·mongodb·面试
掘金-我是哪吒5 小时前
微服务mysql,redis,elasticsearch, kibana,cassandra,mongodb, kafka
redis·mysql·mongodb·elasticsearch·微服务
全能全知者7 小时前
docker快速安装与配置mongoDB
mongodb·docker·容器
齐 飞7 小时前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
暮毅7 小时前
10.Node.js连接MongoDb
数据库·mongodb·node.js
齐 飞1 天前
MongoDB笔记02-MongoDB基本常用命令
前端·数据库·笔记·后端·mongodb
齐 飞1 天前
MongoDB笔记03-MongoDB索引
前端·数据库·笔记·后端·mongodb
威哥爱编程1 天前
MongoDB面试专题33道解析
数据库·mongodb·面试
r i c k2 天前
MongoDB Shell 基本命令(三)聚合管道
mongodb