MongoDB 入门基础详解

本文详细介绍了MongoDB的基本概念和操作,包括数据库、集合、文档、索引等,以及常用的增删改查操作,如等值查找、模糊匹配、排序、统计和分页。还讲解了子文档查询、更新修改器、批量写入和索引创建等高级特性,是MongoDB入门学习的全面指南。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MongoDB是文档型数据库, 与传统关系型数据库有一些区别

概念关系

database 数据库
collection 集合相当于表
docment 文档 相当于行
index 索引
唯一键
mongodb不支持多个集合连接,即是 table join不支持

mongodb 支持多种数据类型

例如:

null 表示空或者不存在的字段
字符串
日期
布尔
数值
正则表达式
数组
对象id (objectID)

一个mongodb中可以建立多个数据库。

"show dbs" 命令可以显示所有数据库的列表

"db" 命令可以显示当前数据库对象或集合

"use"命令,可以连接到一个指定的数据库

文档是一个键值(key-value)对(即BSON)。MongoDB 的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型

最大BSON文档大小为16M字节

_id字段始终是文档中的第一个字段


mongo命令行工具
  1. --help 显示命令行选项
  2. --nodb 在mongo不连接数据库的情况下启动shell。
  3. --shell 允许命令 js
默认全局命令
1. `help`	显示帮助。
2. `db.help()`	显示数据库方法的帮助。
3. `db.<collection>.help()`	显示有关集合方法的帮助。collection可以是现有的集合或不存在的集合的名称。
4. `show dbs`	  服务器上所有数据库的列表。根据用户权限返回不同的值。
5. `use <db>`	切换当前数据库到<db>
6. `show collections`	当前数据库的所有集合的列表。
7. `show users`	当前数据库的用户列表。
8. `show roles`	当前数据库的所有角色列表,包括用户定义和内置角色。
9. `show profile`	花费1毫秒或更长时间的五个最近的操作
10. `show databases`	所有可用数据库的列表。根据用户权限返回不同的值。
11. `load()`	执行JavaScript文件
database 数据库层命令
1. `db.auth()`	用户身份验证。
2. `db.collection.stats()	` 查看文档的一些信息, 例如填充因子
3. `coll = db.<collection>`	将当前数据库中的特定集合设置为变量 coll, 相当于取别名

​		例如: 对myCollection使用变量执行操作, coll  =  db.myCollection,  可以使用别名		调用 coll.find()

3. `db.collection.find()	` 查找集合中的所有文档并返回游标。
4. `db.collection.insertOne()`	将新文档插入集合中。
5. `db.collection.insertMany()`	将多个新文档插入集合中。
6. `db.collection.updateOne()`	更新集合中的单个现有文档。
7. `db.collection.updateMany()`	更新集合中的多个现有文档。
8. `db.collection.save()`	插入新文档或更新集合中的现有文档。
9. `db.collection.deleteOne()`	从集合中删除单个文档。
10. `db.collection.deleteMany()`	从集合中删除文档。
11. `db.collection.drop()`	完全删除或部分删除集合。
12. `db.collection.remove()`	完全删除或部分删除集合。
13. `db.collection.createIndex()`	如果索引不存在,则在集合上创建新索引; 否则,操作无效。
14. `db.getSiblingDB()`	使用此相同连接返回对另一个数据库的引用,而不显式切换当前数据库。这允许跨数据库查询。

增删改查

新增:

db.collection.insert()

db.collection.insertOne() 
db.collection.insertMany()

在插入文档时,如果collection不存在则会新建

新建操作默认情况下,如果没有_id 则会创建一个_id

下面的方法也可能插入新的文档:

db.collection.update() 与参数upsert: true一起使用
db.collection.updateOne()与参数upsert: true一起使用
db.collection.updateMany()与参数upsert: true一起使用
db.collection.findAndModify()与参数upsert: true一起使用
db.collection.findOneAndUpdate()与参数upsert: true一起使用
db.collection.findOneAndReplace()与参数upsert: true一起使用
db.collection.save()
db.collection.bulkWrite()

例如:

// 插入一个数据
db.inventory.insertOne(
   { item: "canvas", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } }
)

// 插入多个数据
db.inventory.insertMany([
   { item: "journal", qty: 25, tags: ["blank", "red"], size: { h: 14, w: 21, uom: "cm" } },
   { item: "mat", qty: 85, tags: ["gray"], size: { h: 27.9, w: 35.5, uom: "cm" } },
   { item: "mousepad", qty: 25, tags: ["gel", "blue"], size: { h: 19, w: 22.85, uom: "cm" } }
])

db.createCollection("people")

添加文档字段:

db.people.updateMany(
    { },
    { $set: { join_date: new Date() } }
)

删除文档字段:

db.people.updateMany(
    { },
    { $unset: { "join_date": "" } }
)

find
findone
例如:

db.inventory.find( {} )

find()和findOne()

find返回一个cusor游标对象, 默认情况下, 打印前20条文档信息

1.`db.collection.find(<query>)`	找到<query>与集合中的条件匹配的文档。如果<query>未指定条件或为空(即{}),则读取操作将选择集合中的所有文档。
2.`db.collection.find(<query>, <projection>)`	查找符合<query>条件的文档,并返回中的特定字段<projection>。默认情况下, _id字段默认返回,除非明确指定不返回
				coll = db.users;    coll.find( { }, { name: true } );
3.`db.collection.find().sort(<sort order>)`	升序(1)返回按字段排序的结果。使用-1降序排序

4.`db.collection.find(<query>).sort(<sort order>)`	返回<query>与指定条件匹配的文档。并进行排序
5.`db.collection.find( ... ).limit( <n> )`	将结果限制为<n>行
6.`db.collection.find( ... ).skip( <n> )`	跳过<n>行结果, 在查找返回很多时候时, 不建议使用
7.`db.collection.count()`	返回集合中的文档总数。
8.`db.collection.find(<query>).count()`	返回与查询匹配的文档总数。在count()时会忽略limit()和skip()。

9.`db.collection.findOne(<query>)`	查找并返回单个文档。如果未找到,则返回null。 等价于find().limit(1)
等值查找:

格式

{ <field1>: <value1>, ... }

例如:

db.inventory.find( { status: "D" } )

模糊匹配

db.users.find( { user_id: /bc/ } )

SELECT * FROM users WHERE user_id like "%bc%"

字符前端模糊匹配:
db.users.find( { user_id: /^bc/ } )

SELECT * FROM users WHERE user_id like "bc%"

排序:

1 asc -1 desc
db.users.find( { status: "A" } ).sort( { user_id: 1 } )

db.users.find( { status: "A" } ).sort( { user_id: -1 } )

count 统计
db.users.count()

db.users.find().count()

db.users.count( { user_id: { $exists: true } } )

db.users.find( { user_id: { $exists: true } } ).count()

db.users.count( { age: { $gt: 30 } } )

db.users.find( { age: { $gt: 30 } } ).count()
去重

db.users.distinct( "status" )

limit

db.users.find().limit(5).skip(10)

3.特殊条件可以使用查询运算符

{ <field1>: { <operator1>: <value1> }, ... }

例如:

db.inventory.find( { status: { $in: [ "A", "D" ] } } )

AND条件:

db.inventory.find( { status: "A", qty: { $lt: 30 } } )

OR:

db.inventory.find( { $or: [ { status: "A" }, { qty: { $lt: 30 } } ] } )
db.users.find({ $or: [ { status: "A" }, { age: 50 } ] })

AND与OR一起:

db.inventory.find( {
     status: "A",
     $or: [ { qty: { $lt: 30 } }, { item: /^p/ } ]
} )
$lt  小于

$lte  小于等于

$gt  大于 

$gte  大于等于

$in  在该数组内值得文档

$not  否

$mod  取模操作

数组查找:

$all  值都存在: {"authors":{“all”:["aaa", "bbb"]}}  表示作者既有aaa,又有bbb的

$size   长度, 查询特定长度的数组

$slice  返回匹配数组元素的子集{“count”: {"$slice": 10}}总数前10

如果为-10, 则为总数最后10个数, 

也可以是一个范围{“count”: {"$slice": [5, 11]}} 总数6-11位置的数, 除去5

$where   键值对的查询方式无法满足查询条件时,可以使用where, 可以在查询中执行任意的JavaScript,进行查找, 一般不进行使用,因为有可能存在安全风险

limit限制返回的大小

skip, 跳过多少文档数, 但是应该避免skip大量结果, 因为拥有一个位置查找过程,因此可能效率比较慢

优化:

使用 find() 和 limit() 实现

考虑根据文档里有的时间戳或者id查询

‘_id’是mongodb ObjectID类型的,ObjectID 使用12 字节的存储空间,每个字节两位十六进制数字,是一个24 位的字符串,包括timestamp, machined, processid, counter 等。
因此可以利用_id做比较分页进行查询

在当前页内查出最后1条记录的_id,记为last_id
把记下来的last_id,作为查询条件,查出大于last_id的记录作为下一页的内容

db.users.find().limit(pageSize);
last_id = x1

//第二页
db.users.find({'_id'> last_id}). limit(pageSize);
last_id = x2
sort排序

查询可以只返回指定字段:

1表示返回, 0 表示不返回,默认返回_id, 除非明确指定不返回_id字段

db.inventory.find( { status: "A" }, { item: 1, status: 1 } )

不返回id:

db.inventory.find( { status: "A" }, { item: 1, status: 1, _id: 0 } )

组合查询/复杂查询

db.user.find({“name”: “aaa”}).sort(“create_time”: 1)

辅助函数:

$maxscan db.user.find()._addSpecial("$maxscan": 20) 扫描文档数量的上限为20条

$min 查询开始条件, 文档必须与索引键完全匹配, 查询会强制使用给定的索引,一般使用 $gt 代替

$max 查询结束条件, 文档必须与索引键完全匹配, 查询会强制使用给定的索引,一般使 用$lg代替

快照

查询过程中, 文档持续修改,更新发送移动,可能在游标末尾,会返回一个新的文档, 解决办法是,可以使用快照snapshot进行查询, 例如: db.user.find().snapshot()

但是快照会影响其他性能,在必要时才进行使用

子文档/嵌套文档查询:

子文档查询字段使用点号"." 例如: profile.address

db.inventory.insertMany( [
   { item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
   { item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "A" },
   { item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
   { item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
   { item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" }
]);
全匹配子文档
db.inventory.find( { size: { h: 14, w: 21, uom: "cm" } } )
查询嵌套文档指定条件:
db.inventory.find( { "size.uom": "aaaa" } 
db.inventory.find( { "size.h": { $lt: 15 } } ))

and 子文档

db.inventory.find( { "size.h": { $lt: 15 }, "size.uom": "in", status: "D" } )

查询数组:

db.inventory.insertMany([
   { item: "journal", qty: 25, tags: ["blank", "red"], dim_cm: [ 14, 21 ] },
   { item: "notebook", qty: 50, tags: ["red", "blank"], dim_cm: [ 14, 21 ] },
   { item: "paper", qty: 100, tags: ["red", "blank", "plain"], dim_cm: [ 14, 21 ] }
]);

等于匹配:

db.inventory.find( { tags: ["red", "blank"] } )

查找既有red又有blank的字段:

db.inventory.find( { tags: { $all: ["red", "blank"] } } )

查找包含一个值:

tags 拥有red的文档

db.inventory.find( { tags: "red" } )

条件匹配:

{ <array field>: { <operator1>: <value1>, ... } }

例如: 查找数组中包含大于25值的文档

db.inventory.find( { dim_cm: { $gt: 25 } } )

小于:

db.users.find({ age: { $lt: 25 } })

范围:

db.inventory.find( { dim_cm: { $gt: 15, $lt: 20 } } )

匹配大小:

db.inventory.find( { "tags": { $size: 3 } } )

匹配指定元素:

查找dim_cm 第二个数大于25

db.inventory.find( { "dim_cm.1": { $gt: 25 } } )

嵌入式文档数组:

查找子文档字段包含条件

db.inventory.find( { "instock": { warehouse: "A", qty: 5 } } )

小于等于

db.inventory.find( { 'instock.qty': { $lte: 20 } } )

范围匹配

db.inventory.find( { "instock.qty": { $gt: 10, $lte: 20 } }

多个条件匹配

db.inventory.find( { "instock.qty": 5, "instock.warehouse": "A" } )

嵌入式文档也可以进行限制返回的字段:

db.inventory.find( { status: "A" }, { item: 1, status: 1, "instock.qty": 1 } )

1.查询null字段:

一般查询等于null的字段, 会返回等于null的字段同时也会匹配到不包含该字段的文档

因此一般不进行null的字段查找,若需要查找,可以通过引用将指定的字段为null的值设置为特殊的字符串进行匹配

db.inventory.find( { item: null } )

2.类型查找:

10 为bson类型编号

db.inventory.find( { item : { $type: 10 } } )

3.存在性校验

$exists

db.inventory.find( { item : { $exists: false } } )

更新:

db.collection.updateOne() 
db.collection.updateMany()
db.collection.replaceOne()

语法:

{
  <update operator>: { <field1>: <value1>, ... },
  <update operator>: { <field2>: <value2>, ... },
  ...
}

$set 如果该字段不存在这会创建对应的字段

例如:

db.inventory.updateOne(
   { item: "paper" },
   {
     $set: { "size.uom": "cm", status: "P" },
     $currentDate: { lastModified: true }
   }
)

更新多个文档:

db.inventory.updateMany(
   { "qty": { $lt: 50 } },
   {
     $set: { "size.uom": "in", status: "P" },
     $currentDate: { lastModified: true }
   }
)

字段加: age = age +3

db.users.update(
   { status: "A" } ,
   { $inc: { age: 3 } },
   { multi: true }
)
替换文档:
db.inventory.replaceOne(
   { item: "paper" },
   { item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 40 } ] }
)

MongoDB会维护文档的写入顺序,也就是相邻的,但是有时候,更新一个文档变大了, 原来的位置无法存放下文档了, 只能移动到新的位置
MongoDB也存在预留空间,也就是填充因子, 填充因子是MongoDB为每个新闻的预留的增长空间, 可以使用db.collection.stats() 查看, paddingFactor 即是填充因子,
新增时为1,表示不预留任何增长空间, 如果增加文档,则文档发送移动,增长因子变为1.5
预留一半的空间, 多次移动会持续增长,但是不会增长那么快了
移动文档时非常缓慢的操作, 因此应尽量避免移动文档。 移动文档时,需要将原来空间释放掉,再写入另外一个空间。
此外,文档发生移动,原来的空间闲置, 产生空白空间,这就可能带来大量的碎片空间,并且无法利用, 除非进行压缩

更新修改器:
1. $set 设置指定字段

2. $inc  增加或者减少数字

3. $ push   数组操作, 数组存在,则会向已有数组末尾加入一个新的元素,如果没有,则创建

   例如: db.mct.update({"user":"aaa"}, {"push": {"context": "qbc"})

   $each一次添加多个值, 例如:

   db.mct.update({"user":"aaa"}, {"push": {"context": {"$each":[1,2,3]}}

   添加1,2,3 一共3个值

   可以和$slice一起使用,限制大小, $slice 必须是负整数

   db.mct.update({"user":"aaa"}, {"push": {"context": {"$each":[1,2,3], "$slice": -10}}) 限制数组只包含最后加入的10个元素

4. $ne  不等于, 可以保证数组的元素不重复

   db.mct.update({"user":{"$ne": "aaa"}}, {"push": {"user": "aaa"}}

5. $addToSet   添加到数组

   db.mct.update({"_id": "xxxx"}, {"addToSet": {"user": "aaa"}}

   也可以和$each组合一次添加多个值

6. $pop  删除元素, 可以从头或者尾删除

   {"$pop": {"key": -1}} 从头部删除, 为1表示尾部删除

7. $pull 依据特定条件进行删除:

   db.mct.update({"_id": "xxxx"}, {"pull": {"user": "aaa"}}

   删除user中的aaa元素

8. 基于数组位置的修改, 数组的下标都是0开始的

   db.mct.update({"_id": "xxxx"}, {"inc": {"user.0.count": 1}}

删除:

delete

db.collection.deleteOne() 
db.collection.deleteMany()
db.collection.remove()

删除所有:

db.inventory.deleteMany({})

删除一条数据:

db.inventory.deleteOne( { status: "D" } )

删除操作不会删除索引,即使删除所有文档也不会删除索引

批量写入:

如果在处理其中一个写操作期间发生错误,MongoDB将返回而不处理列表中的任何剩余写操作

创建索引:

1 表示asc, -1表示desc 降序

db.people.createIndex( { user_id: 1 } )

db.users.createIndex( { user_id: 1, age: -1 } )


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值