文章目录
- MongoDB
- MongoDB认识
- mongodb的技术优势
- MongoDB应用场景
- MongoDB部署和连接
- 常用命令
- MongoDB安全认证
- 测试用户和集合的创建
- 查询和排序命令
- 更新文档命令
- upsert命令
- replace命令
- findAndModify命令
- 删除文档
- remove命令
- delete命令
- 返回被删除文档
MongoDB
MongoDB认识
-
MongoDB是一个以JSON 为数据模型的文档数据库,由C++语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案。
文档来自于"JSON Document",并非一般的 PDF,WORD 文档。
-
MongoDB介于关系数据库和非关系数据库之间,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,数据格式是BSON,一种类似JSON的二进制形式的存储格式,简称Binary JSON,和JSON一样支持内嵌的文档对象和数组对象,因此可以存储比较复杂的数据类型。
- BSON是一种二进制形式的存储格式,它是 JSON 的二进制版本。BSON 格式的数据可以在 MongoDB 中存储和传输,它支持内嵌的文档对象和数组对象,因此可以存储比较复杂的数据类型。
-
MongoDB最大的特点是查询语言强大,语法类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引l,原则上支持ACID事务。
-
MongoDB与关系型数据库(RDBMS)对比
SQL概念 | MongonDB概念 |
---|---|
数据表库(database) | 数据库(database) |
表(table) | 集合(collection) |
行(row) | 文档(document) |
列(column) | 字段(filed) |
索引(index) | 索引(index) |
主键(primary key) | _id(字段) |
视图(view) | 视图(view) |
表连接(table jions) | 聚合操作($lookup) |
两者的数据存储(逻辑视图)
- RDBMS
id | name | age |
---|---|---|
1 | John Doe | 30 |
- MongoDB
{ "_id": ObjectId("5f9d7c8a8c9d8a7c6a8d7c6a"), "name": "John Doe", "age": 30 }
mongodb的技术优势
- 灵活的数据模型:MongoDB 使用类似 JSON 的文档格式存储数据,字段可以动态添加或删除,非常适合处理半结构化和非结构化数据。
- 高可扩展性:MongoDB 支持水平扩展,可以通过添加更多的节点来提高数据库的性能和容量。
- 高性能:MongoDB 对写入操作进行了优化,可以快速处理大量的写入请求。同时,它也支持索引和查询优化,可以提高查询性能。
- 丰富的查询语言:MongoDB 提供了强大的查询语言,可以方便地进行复杂的查询操作,包括文本搜索、地理空间查询等。
- 高可用性:MongoDB 支持副本集和分片,可以提高数据库的可用性和容错性。
- 易于开发和使用:MongoDB 的 API 简单易用,支持多种编程语言,开发人员可以快速上手。
MongoDB应用场景
场景 | MongoDB应用说明 |
---|---|
游戏场景 | 使用 MongoDB 存储游戏用户信息,包括用户的装备、积分等,以内嵌文档形式存储,便于查询和更新。 |
物流场景 | 使用 MongoDB 存储订单信息,订单状态在运送过程中不断更新,以MongoDB内嵌数组形式存储,一次查询即可读取所有变更。 |
社交场景 | 使用 MongoDB 存储用户信息及其发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能。 |
物联网场景 | 使用 MongoDB 存储所有接入的智能设备信息及设备汇报的日志信息,并进行多维度分析。 |
视频直播 | 使用 MongoDB 存储用户信息、礼物信息等。 |
大数据应用 | 使用云数据库 MongoDB 作为大数据的云存储系统,便于随时进行数据提取分析,掌握行业动态。 |
- 使用场景,满足其中一个即可
应用场景 |
---|
应用需要2000-3000以上的读写QPS(更高也可以) |
应用不需要复杂/长事务及join支持 |
新应用,需求会变,数据模型无法确定,想快速迭代开发 |
应用需要TB甚至PB级别数据存储 |
应用发展迅速,需要能快速水平扩展 |
应用要求存储的数据不丢失 |
应用需要99.999%高可用 |
应用需要大量的地理位置查询、文本查询 |
MongoDB部署和连接
- 1panel快速部署,MongoDB Compass连接或者1panel面板,进入终端容器
root@da16145ff0e1:/# mongosh -u "mongodb" -p "mongodb" --authenticationDatabase "admin"
Current Mongosh Log ID: 66896df3bf843ea3518db5fa
Connecting to: mongodb://<credentials>@127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&authSource=admin&appName=mongosh+2.2.6
Using MongoDB: 7.0.11
Using Mongosh: 2.2.6
For mongosh info see: https://docs.mongodb.com/mongodb-shell/
------
The server generated these startup warnings when booting
2024-07-06T15:09:36.112+00:00: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine. See http://dochub.mongodb.org/core/prodnotes-filesystem
2024-07-06T15:09:39.092+00:00: vm.max_map_count is too low
------
test> show dbs
admin 100.00 KiB
config 96.00 KiB
local 72.00 KiB
test 40.00 KiB
test>
# mongosh
Current Mongosh Log ID: 666ab60286d9f2e6e88db5fa
Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.2.6
Using MongoDB: 7.0.11
Using Mongosh: 2.2.6
For mongosh info see: https://docs.mongodb.com/mongodb-shell/
To help improve our products, anonymous usage data is collected and sent to MongoDB periodically (https://www.mongodb.com/legal/privacy-policy).
You can opt-out by running the disableTelemetry() command.
test> db.runCommand(
... {
... hello: 1
... }
... )
{
isWritablePrimary: true,
topologyVersion: {
processId: ObjectId('666aae2947f5799e146c4447'),
counter: Long('0')
},
maxBsonObjectSize: 16777216,
maxMessageSizeBytes: 48000000,
maxWriteBatchSize: 100000,
localTime: ISODate('2024-06-13T09:04:31.849Z'),
logicalSessionTimeoutMinutes: 30,
connectionId: 40,
minWireVersion: 0,
maxWireVersion: 21,
readOnly: false,
ok: 1
}
常用命令
命令说明 | 描述 |
---|---|
` show dbs | show databases` |
use 数据库名 | 切换到指定名称的数据库,如果不存在则创建该数据库 |
db.dropDatabase() | 删除当前所在的数据库 |
`show collections | show tables` |
db.集合名.stats() | 查看集合详情 |
db.集合名.drop() | 删除集合 |
show users | 显示当前数据库的用户列表 |
show roles | 显示当前数据库的角色列表 |
show profile | 显示最近操作的概要 |
load("xxx.js") | 执行指定的JavaScript脚本文件 |
exit或者quit | 退出当前shell |
help | 查看 MongoDB 支持的命令列表 |
db.help() | 查看当前数据库支持的方法 |
db.集合名.help() | 显示指定集合的帮助信息 |
db.version() | 查看 MongoDB 数据库版本 |
MongoDB安全认证
- 创建管理员账号
use admin
db.createUser({user:"fox",pwd:"fox",roles:["root"]})
show users
db.dropUser("fox")
- 常用权限
权限名 | 描述 |
---|---|
read | 允许用户读取指定数据库 |
readwrite | 允许用户读写指定数据库 |
dbAdmin | 允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile |
dbOwner | 允许用户在指定数据库中执行任意操作,增、删、改、查等 |
userAdmin | 允许用户向system.users集合写入,可以在指定数据库里创建、删除和管理用户 |
clusterAdmin | 只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限 |
readAnyDatabase | 只在admin数据库中可用,赋予用户所有数据库的读权限 |
readWriteAnyDatabase | 只在admin数据库中可用,赋予用户所有数据库的读写权限 |
userAdminAnyDatabase | 只在admin数据库中可用,赋予用户所有数据库的userAdmin权限 |
dbAdminAnyDatabase | 只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限 |
root | 只在admin数据库中可用,超级账号,超级权限 |
> use admin
< switched to db admin
> db.createUser({user:"fox",pwd:"fox",roles:["root"]})
< { ok: 1 }
> show users
< [
{
_id: 'admin.fox',
userId: UUID('ecc3e266-eff7-4b1e-a397-bd55555572ad'),
user: 'fox',
db: 'admin',
roles: [
{
role: 'root',
db: 'admin'
}
],
mechanisms: [
'SCRAM-SHA-1',
'SCRAM-SHA-256'
]
},
{
_id: 'admin.mongodb',
userId: UUID('ff8cf353-9600-4721-acd2-7b71a56254ad'),
user: 'mongodb',
db: 'admin',
roles: [
{
role: 'root',
db: 'admin'
}
],
mechanisms: [
'SCRAM-SHA-1',
'SCRAM-SHA-256'
]
}
]
> db.dropUser('fox')
< { ok: 1 }
-
创建应用数据库用户
use appdb db.createUser({user:"appdb",pwd:"fox",roles:"dbOwner"})
-
默认情况下,,MongoDB不会启用鉴权,以鉴权模式启动MongoDB,启用鉴权之后,连接MopgoDB的相关操作都需要提供身份认证。
mongod -f/mongodb/conf/mongo.conf --auth mongo 192.168.5.11:27017 -u fox -p fox --authenticationDatabase=admin
root@da16145ff0e1:/# mongosh -u fox -p fox --authenticationDatabase=admin
Current Mongosh Log ID: 6689fe6687d45d41978db5fa
Connecting to: mongodb://<credentials>@127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&authSource=admin&appName=mongosh+2.2.6
Using MongoDB: 7.0.11
Using Mongosh: 2.2.6
For mongosh info see: https://docs.mongodb.com/mongodb-shell/
------
The server generated these startup warnings when booting
2024-07-06T15:09:36.112+00:00: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine. See http://dochub.mongodb.org/core/prodnotes-filesystem
2024-07-06T15:09:39.092+00:00: vm.max_map_count is too low
------
test>
测试用户和集合的创建
- 创建用户和数据库、集合,并插入数据
use admin
already on db admin
db.createUser({
user: "myuser",
pwd: "mypassword",
roles: [ { role: "readWrite", db: "mydatabase" } ]
})
{ ok: 1 }
use myuser
switched to db myuser
use mydatabase
switched to db mydatabase
db.createCollection("mycollection")
{ ok: 1 }
db.mycollection.insertOne({ name: "Alice", age: 25 })
{
acknowledged: true,
insertedId: ObjectId('668a05dbdca15ef5aa639e2b')
}
db.mycollection.insertOne({ name: "Bob", age: 30 })
{
acknowledged: true,
insertedId: ObjectId('668a05e0dca15ef5aa639e2c')
}
db.mycollection.find()
{
_id: ObjectId('668a05dbdca15ef5aa639e2b'),
name: 'Alice',
age: 25
}
{
_id: ObjectId('668a05e0dca15ef5aa639e2c'),
name: 'Bob',
age: 30
}
db.mycollection.insertMany([
{ name: "Charlie", age: 35 },
{ name: "David", age: 40 },
{ name: "Eve", age: 45 }
])
db.mycollection.insertMany([
{ name: "Charlie", age: 35 },
{ name: "David", age: 40 },
{ name: "Eve", age: 45 }
])
- 方式一:直接MongoSh执行,或者在Navicat中查询页面执行
var tags = ["nosql", "mongodb", "document", "developer", "popular"];
var types = ["technology", "sociality", "travel", "novel", "literature"];
var books = [];
for (var i = 0; i < 50; i++) {
var typeIdx = Math.floor(Math.random() * types.length);
var tagIdx = Math.floor(Math.random() * tags.length);
var favcount = Math.floor(Math.random() * 100);
var book = {
title: "book-" + i,
type: types[typeIdx],
tag: tags[tagIdx],
favcount: favcount,
author: "author" + i
};
books.push(book);
}
db.books.insertMany(books);
- 方式二:将其存储位js文件,然后执行脚本
load inserData.js
。或者在Navicat中选中数据库,执行脚本文件,Mongo Compass中执行不成功。
查询和排序命令
MySQL 和 MongoDB 在条件查询的查询条件对比整理为表格展示:
功能 | MySQL (SQL) | MongoDB (Mongo Shell) |
---|---|---|
选择所有记录 | SELECT * FROM table_name; | db.collection_name.find({}); |
选择特定字段 | SELECT column1, column2 FROM table_name; | db.collection_name.find({}, {column1: 1, column2: 1}); |
条件查询 (等于) | SELECT * FROM table_name WHERE column1 = 'value'; | db.collection_name.find({column1: 'value'}); |
条件查询 (不等于) | SELECT * FROM table_name WHERE column1 != 'value'; | db.collection_name.find({column1: {$ne: 'value'}}); |
条件查询 (大于) | SELECT * FROM table_name WHERE column1 > value; | db.collection_name.find({column1: {$gt: value}}); |
条件查询 (大于等于) | SELECT * FROM table_name WHERE column1 >= value; | db.collection_name.find({column1: {$gte: value}}); |
条件查询 (小于) | SELECT * FROM table_name WHERE column1 < value; | db.collection_name.find({column1: {$lt: value}}); |
条件查询 (小于等于) | SELECT * FROM table_name WHERE column1 <= value; | db.collection_name.find({column1: {$lte: value}}); |
条件查询 (IN) | SELECT * FROM table_name WHERE column1 IN ('value1', 'value2'); | db.collection_name.find({column1: {$in: ['value1', 'value2']}}); |
条件查询 (NOT IN) | SELECT * FROM table_name WHERE column1 NOT IN ('value1', 'value2'); | db.collection_name.find({column1: {$nin: ['value1', 'value2']}}); |
条件查询 (LIKE) | SELECT * FROM table_name WHERE column1 LIKE '%value%'; | db.collection_name.find({column1: /value/}); |
条件查询 (AND) | SELECT * FROM table_name WHERE column1 = 'value1' AND column2 = 'value2'; | db.collection_name.find({column1: 'value1', column2: 'value2'}); |
条件查询 (OR) | SELECT * FROM table_name WHERE column1 = 'value1' OR column2 = 'value2'; | db.collection_name.find({$or: [{column1: 'value1'}, {column2: 'value2'}]}); |
排序 | SELECT * FROM table_name ORDER BY column1 ASC/DESC; | db.collection_name.find({}).sort({column1: 1/-1}); |
限制结果数量 | SELECT * FROM table_name LIMIT 10; | db.collection_name.find({}).limit(10); |
分页 | SELECT * FROM table_name LIMIT 10 OFFSET 20; | db.collection_name.find({}).skip(20).limit(10); |
- 查询逻辑对照表
SQL | MQL |
---|---|
a=1 | {a:1} |
a<>1 | {a:{$gt:1}} |
a>1 | {a:{$gte:1}} |
a<1 | {a:{$lt:1}} |
a<=1 | {a:{$lte:1}} |
a=1 AND b=1 | {a:1,b:1}或{$and:[{a:1},{b:1}]} |
a=1 OR b=0 | {$or:[{a:1},{b:1}]} |
a IS NULL | {a:{$exits:false}} |
a IN (1,2,3) | {a:{$in:[1,2,3]}} |
- 使用sort()方法对数据进行排序
// 指定按收藏数(favCount)降序返回 1升序,-1降序
db.books.find({type:"travel"}).sort({favcount:-1})
-
分页查询skip用于指定跳过记录数,limit则用于限定返回结果数量。可以在执行find命令的同时指定skip、limit参数,以此实现分页的功能。比如,假定每页大小为8条,查询第3页的book文档:
db.books.find() .skip(8).limit(4)
-
正则表达式匹配查询:MongoDB使用$regex操作符来设置匹配字符串的正则表达式
// 使用正则表达式查找type包含so字符串的book
db.books.find({type:{$regex:"so"}})
// 或者
db.books.find({type:/so/})
更新文档命令
db.collection.update(query,update,options)
-
query:描述更新的查询条件
-
update:描述更新的动作及新的内容
-
options:
- upsert:可选,如果不存在update的记录,是否插入新的记录。默认false,不插入
- multi:可选,是否按条件查询出的多条记录全部更新。默认false,只更新找到的第一条记录
- writeConcern:可选,决定一个写操作落到多少个节点上才算成功。
-
更新操作符
操作符 | 格式 | 描述 |
---|---|---|
$set | {$set:{field:value}} | 指定一个键并更新值,若键不存在则创建 |
$unset | {$unset:{field:1}} | 删除—个键 |
$inc | {$inc : {field : value }} | 对数值类型进行增减 |
$rename | {$rename : {old_field_name : new_field_name }} | 修改字段名称 |
$push | {$push : {field : value }} | 将数值追加到数组中,若数组不存在则会进行初始化 |
$pushAll | {$pushAll : {field : value_array } | 追加多个值到一个数组字段内 |
$pull | {$pull : {field : _value }} | 从数组中删除指定的元素 |
$addToSet | {$addToSet : {field : value }} | 添加元素到数组中,具有排重功能 |
$pop | {$pop : {field : 1} | 删除数组的第一个或最后一个元素 |
-
更新单个文档:某个book文档被收藏了,则需要将该文档的favCount字段自增
db.books :update({_id:0bjectId("61caa09ee0782536660494d9")},{$inc: {favcount:1}})
-
更新多个文档:默认情况下,update命令只在更新第一个文档之后返回,如果需要更新多个文档,则可以使用multi选项。将分类为"novel"的文档的增加发布时间(publishedDate)
db.books.update({type:"novel"},{$set: {publishedDate:new Date()}},{"multi":true})
- multi:可选,mongodb默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新
-
update命令的选项配置较多,为了简化使用还可以使用一些快捷命令:
- updateOne:更新单个文档。
- updateMany:更新多个文档。
- replaceOne:替换单个文档。
upsert命令
- upsert是一种特殊的更新,其表现为如果目标文档不存在,则执行插入命令,nMatched、nModified都为0,表示没有文档被匹配及更新,nUpserted=1提示执行了upsert动作
db.books.update(
{title:"my book"},
{$set:{tags:["nosql","mongodb"],type:"none",author:"fox",favcount:30}},
{upsert:true}
)
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("668aa86c6819344d94bc709c"),
"writeConcernError" : [ ]
})
replace命令
- update命令中的更新描述(update)通常由操作符描述,如果更新描述中不包含任何操作符,那么MongoDB会实现文档的replace语义
db.books.update(
{title:"my book"},
{title:"new book"}
)
WriteResult({
"nMatched" : 1,
"nUpserted" : 0,
"nModified" : 1,
"writeConcernError" : [ ]
})
db.books.find({title:"new book"})
{
"_id": ObjectId("668aa86c6819344d94bc709c"),
"title": "new book"
}
findAndModify命令
- findAndModify兼容查询和修改指定文档的功能,但只能更新单个文档,该操作会返回符合查询条件的旧文档数据,并完成对文档的修改。
//将某个book文档的收藏数(favcount)加1
db.books.findAndModify({
query:{title:"new book"},
update:{$inc:{favcount:1}}
})
// 1
{
"_id": ObjectId("668aa86c6819344d94bc709c"),
"title": "new book",
"author": "fox",
"favcount": 32,
"tags": [
"nosql",
"mongodb"
],
"type": "none"
}
删除文档
remove命令
- remove命令需要配合查询条件使用
- 匹配查询条件的文档会被删除
- 指定一个空文档条件会删除所有文档
db.user.remove({})//删除所有记录
db.user.remove()//报错
db.user.remove({age:28}) // 删除age 等于28的记录
db.user.remove({age:{$]t:25}})// 删除age 小于25的记录
- remove命令会删除匹配条件的全部文档,如果希望明确限定只删除一个文档,则需要指定justOne参数
db.collection.remove(query,justone)
delete命令
- 使用deleteOne()和deleteMany()方法删除文档
//删除集合下全部文档
db.books.deleteMany({})
//删除type等于nove1的全部文档
db.books.deleteMany({type:"novel" }))
//删除 type等于novel的一个文档
db.books.delete0ne({type:"novel"})
- remove、deleteMany等命令需要对查询范围内的文档逐个删除,如果希望删除整个集合,使用drop命令会更加高效
返回被删除文档
-
remove、deleteOne等命令在删除文档后只会返回确认性的信息,如果希望获得被删除的文档,则可以使用findOneAndDelete命令.
db.books.findoneAndDelete({type:"novel"})
-
除了在结果中返回删除文档,findOneAndDelete命令还允许定义"删除的顺序",即按照指定顺序删除找到的第一个文档。
db.books.findoneAndDelete({type:"nove]"},{sort:{favcount:1}})
-
remove、deleteOne等命令只能按默认顺序删除,利用这个特性,findOneAndDelete可以实现队列的先进先出。