目录
[1. 简单介绍](#1. 简单介绍)
[使用mongoDB-ui -》studio-3t](#使用mongoDB-ui -》studio-3t)
数据库的种类
常见的数据库有关系型数据库,非关系型数据库。
关系型数据库
mysql
关系型数据库:
基于关系模型,数据以表格的形式存储,每个表由行(记录)和列(字段)组成。
表与表之间通过外键等关系进行关联,形成复杂的结构。
数据的结构化程度高,适合存储结构化数据。
强调 ACID(原子性、一致性、隔离性、持久性)特性,确保数据的完整性和一致性。
适合对数据一致性要求较高的场景,如金融交易系统。
适合复杂查询(多表关联等)、事务处理、数据完整性要求高的场景,如企业资源规划(ERP)、金融系统、库存管理等。
非关系型数据库
非关系型数据库:
不依赖于传统的表格结构,有多种类型,包括键值存储(如 Redis)、文档存储(如 MongoDB)、列存储(如 Cassandra)和图数据库(如 Neo4j)。
数据存储更加灵活,适合存储半结构化或非结构化数据。
查询语言通常基于特定的数据库类型。例如:
键值存储数据库通常通过键直接访问值。
文档存储数据库使用类似 JSON 的查询语言(如 MongoDB 的 BSON)。
图数据库使用图查询语言(如 Cypher)。
查询语言相对灵活,但功能可能不如 SQL 强大。
适合处理大规模数据、高并发读写、灵活数据结构的场景,如社交媒体数据、日志存储、物联网数据等。
如非关系型数据库有
- (内存数据库)redis:适用场景有 缓存热点数据,分布式锁,临时存放数据的中间站(如合并运单)
- (图数据库)neo4j:适用场景有 存储每个数据之间都有强烈关系的信息,如路线规划,族谱管理
- (全文搜索引擎)es:使用场景 需要从海量数据中查询出对应的数据,如酒店查询,商品查询
- (文档型数据库)mongoDB:适用场景 可以直接存储坐标这样的数据,所以可以用于存储作用范围 也可以存储物流信息
MongoDB
1. 简单介绍
MongoDB是一个基于分布式文件存储的数据库
由C++语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。
Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
传统的关系型数据库(如MySQL),在数据操作的三高需求以及应对Web2.0的网站需求面前,显得力不从心,而 MongoDB可应对"三高"需求
High performance:对数据库高并发读写的需求
Huge Storage:对海量数据的高效率存储和访问的需求
High Scalability && High Availability:对数据库的高可扩展性和高可用性的需求
2.使用场景:
社交场景,使用 MongoDB存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能。
游戏场景,使用 MongoDB存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、高效率存储和访问。
物流场景,使用 MongoDB存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来
物联网场景,使用 MongoDB存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析。
视频直播,使用 MongoDB存储用户信息、点赞互动信息等。
这些应用场景中,数据操作方面的共同特点是:
(1)数据量大
(2)写入操作频繁(读写都很频繁)
(3)价值较低的数据,对事务性要求不高
对于这样的数据,我们更适合使用 MongoDB来实现数据的存储。
3.什么时侯选择MongoDB
- 应用不需要事务及复杂join支持(多表查询)
- 新应用,需求会变,数据模型无法确定,想快速迭代开发
- 应用需要2000-3000以上的读写QPS(更高也可以)
- 应用需要TB甚至PB级别数据存储
- 应用要求存储的数据不丢失
- 应用需要99.999%高可用
- 应用需要大量的地理位置查询、文本查
- 相对MySQL,在以上以用场景可以以更低的成本解决问题(包括学习、开发、运维等成本)
4.基本概念 (也mysql对比)
与SQL中的概念进行对比:
|--------------|------------------|-------------------------|
| SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
| database | database | 数据库 |
| table | collection | 数据库表/集合 |
| row | document | 数据记录行/文档 |
| column | field | 数据字段/域 |
| index | index | 索引 |
| table joins | | 表连接,MongoDB不支持 |
| primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |

5.docker安装mongoDB
docker run -d \
--name mongodb \
-p 27017:27017 \
--restart=always \
-v mongodb:/data/db \
-e MONGO_INITDB_ROOT_USERNAME=sl \
-e MONGO_INITDB_ROOT_PASSWORD=123321 \
mongo:4.4
6.简单使用mongoDB
#进入容器进行设置
docker exec -it mongodb /bin/bash
#进行认证
mongo -u "sl" -p "123321" --authenticationDatabase "admin"

库和表的操作
#查看所有的数据库
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
#通过use关键字切换数据库
> use admin
switched to db admin
#创建数据库
#说明:在MongoDB中,数据库是自动创建的,通过use切换到新数据库中,进行插入数据即可自动创建数据库
> use testdb
switched to db testdb
> show dbs #并没有创建数据库
admin 0.000GB
config 0.000GB
local 0.000GB
> db.user.insert({id:1,name:'zhangsan'}) #插入数据
WriteResult({ "nInserted" : 1 })
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
testdb 0.000GB #数据库自动创建
#查看表
> show tables
user
> show collections
user
>
#删除集合(表)
> db.user.drop()
true #如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false。
#删除数据库
> use testdb #先切换到要删除的数据库中
switched to db testdb
> db.dropDatabase() #删除数据库
{ "dropped" : "testdb", "ok" : 1 }
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
插入数据
在MongoDB中,存储的文档结构是一种类似于json的结构,称之为bson(全称为:Binary JSON)。
#插入数据
#语法:db.COLLECTION_NAME.insert(document)
> use testdb
switched to db testdb
> db.user.insert({id:1,username:'zhangsan',age:20})//插入数据
WriteResult({ "nInserted" : 1 })
> db.user.insert({id:2,username:'zhangsan',sex:'男'})//可以在同一个集合里插入不同类型的数据,没有严格要求
WriteResult({ "nInserted" : 1 })
//查询集合的所有文档数据
> db.user.find()
{ "_id" : ObjectId("67b735a36c674f9f2b6e0776"), "id" : 1, "username" : "zhangsan", "age" : 20 }
{ "_id" : ObjectId("67b735c36c674f9f2b6e0777"), "id" : 2, "username" : "zhangsan", "sex" : "男" }
//使用insert插入_id主键一样的数据时就会报错
> db.user.insert({"_id" : ObjectId("67b735a36c674f9f2b6e0776"), "id" : 1, "username" : "zhangsan", "age" : 20})
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: testdb.user index: id dup key: { _id: ObjectId('67b735a36c674f9f2b6e0776') }"
}
})
//使用save方法不会报错,可以直接覆盖原来的数据
> db.user.save({"_id" : ObjectId("67b735a36c674f9f2b6e0776"), "id" : 1, "username" : "zhangsan"})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.find()
{ "_id" : ObjectId("67b735a36c674f9f2b6e0776"), "id" : 1, "username" : "zhangsan" }
{ "_id" : ObjectId("67b735c36c674f9f2b6e0777"), "id" : 2, "username" : "zhangsan", "sex" : "男" }
- *id 是集合中文档的主键,用于区分文档(记录),*id自动编入索引。
- 默认情况下,id 字段的类型为 ObjectID,是 MongoDB 的 BSON 类型之一,如果需要,用户还可以将id 覆盖为 ObjectID 以外的其他内容。
- ObjectID 长度为 12 字节,由几个 2-4 字节的链组成。每个链代表并指定文档身份的具体内容。以下的值构成了完整的 12 字节组合:
-
- 一个 4 字节的值,表示自 Unix 纪元以来的秒数
- 一个 3 字节的机器标识符
- 一个 2 字节的进程 ID
- 一个 3字节的计数器,以随机值开始
更新数据
update() 方法用于更新已存在的文档。语法格式如下:
db.collection.update(
<query>,
<update>,
[
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
]
)
参数说明:
- query : update的查询条件,类似sql update查询内where后面的。
- update : update的对象和一些更新的操作符(如,inc...)等,也可以理解为sql update查询内set后面的
- upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
- multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
- writeConcern :可选,抛出异常的级别。
> db.user.find()
{ "_id" : ObjectId("5c08c0024b318926e0c1f6dc"), "id" : 1, "username" : "zhangsan", "age" : 20 }
{ "_id" : ObjectId("5c08c0134b318926e0c1f6dd"), "id" : 2, "username" : "lisi", "age" : 25 }
//$set相当于mysql中的update的set关键字,如果没有age字段,就会添加这个字段,而不是覆盖
> db.user.update({id:1},{$set:{age:22}}) #更新数据
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.find()
{ "_id" : ObjectId("5c08c0024b318926e0c1f6dc"), "id" : 1, "username" : "zhangsan", "age" : 22 }
{ "_id" : ObjectId("5c08c0134b318926e0c1f6dd"), "id" : 2, "username" : "lisi", "age" : 25 }
//注意:如果这样写,会删除掉其他的字段,不是用$set,就会直接覆盖原来的数据
> db.user.update({id:1},{age:25})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.find()
{ "_id" : ObjectId("5c08c0024b318926e0c1f6dc"), "age" : 25 }
{ "_id" : ObjectId("5c08c0134b318926e0c1f6dd"), "id" : 2, "username" : "lisi", "age" : 25 }
//更新不存在的字段,会新增字段> db.user.update({id:2},{$set:{sex:1}}) #更新数据
> db.user.find()
{ "_id" : ObjectId("5c08c0024b318926e0c1f6dc"), "age" : 25 }
{ "_id" : ObjectId("5c08c0134b318926e0c1f6dd"), "id" : 2, "username" : "lisi", "age" : 25, "sex" : 1 }
//更新不存在的数据,默认不会新增数据> db.user.update({id:3},{$set:{sex:1}})
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
> db.user.find()
{ "_id" : ObjectId("5c08c0024b318926e0c1f6dc"), "age" : 25 }
{ "_id" : ObjectId("5c08c0134b318926e0c1f6dd"), "id" : 2, "username" : "lisi", "age" : 25, "sex" : 1 }
//如果设置第一个参数为true,就是新增数据> db.user.update({id:3},{$set:{sex:1}},true)
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("5c08cb281418d073246bc642")
})
> db.user.find()
{ "_id" : ObjectId("5c08c0024b318926e0c1f6dc"), "age" : 25 }
{ "_id" : ObjectId("5c08c0134b318926e0c1f6dd"), "id" : 2, "username" : "lisi", "age" : 25, "sex" : 1 }
{ "_id" : ObjectId("5c08cb281418d073246bc642"), "id" : 3, "sex" : 1 }
//同时修改多条数据,第二个参数也设置为true
> db.user.update({sex:1},{$set:{sex:2}},true,true)
> db.user.find()
{ "_id" : ObjectId("5c08c0024b318926e0c1f6dc"), "age" : 25 }
{ "_id" : ObjectId("5c08c0134b318926e0c1f6dd"), "id" : 2, "username" : "lisi", "age" : 25, "sex" : 2 }
{ "_id" : ObjectId("5c08cb281418d073246bc642"), "id" : 3, "sex" : 2 }
删除数据
通过remove()方法进行删除数据,语法如下:
db.collection.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)
参数说明:
- query :(可选)删除的文档的条件。
- justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
- writeConcern :(可选)抛出异常的级别。
> db.user.remove({age:25})
WriteResult({ "nRemoved" : 2 }) #删除了2条数据
#插入4条测试数据
db.user.insert({id:1,username:'zhangsan',age:20})
db.user.insert({id:2,username:'lisi',age:21})
db.user.insert({id:3,username:'wangwu',age:22})
db.user.insert({id:4,username:'zhaoliu',age:22})
> db.user.remove({age:22},true)
WriteResult({ "nRemoved" : 1 }) #删除了1条数据
#删除所有数据
> db.user.remove({})
#说明:为了简化操作,官方推荐使用deleteOne()与deleteMany()进行删除数据操作。
db.user.deleteOne({id:1})
db.user.deleteMany({}) #删除所有数据
查询数据
MongoDB 查询数据的语法格式为:db.user.find([query],[fields])
- query :可选,使用查询操作符指定查询条件
- fields :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式为:db.col.find().pretty()
条件查询:
|--------|------------|-------------------------------------------|--------------------|
| 操作 | 格式 | 范例 | RDBMS中的类似语句 |
| 等于 | {:} | db.col.find({"by":"程序员"}).pretty() | where by = '程序员' |
| 小于 | {:{lt:}} | db.col.find({"likes":{lt:50}}).pretty() | where likes < 50 |
| 小于或等于 | {:{lte:}} | db.col.find({"likes":{lte:50}}).pretty() | where likes <= 50 |
| 大于 | {:{gt:}} | db.col.find({"likes":{gt:50}}).pretty() | where likes > 50 |
| 大于或等于 | {:{gte:}} | db.col.find({"likes":{gte:50}}).pretty() | where likes >= 50 |
| 不等于 | {:{ne:}} | db.col.find({"likes":{ne:50}}).pretty() | where likes != 50 |
> db.user.insert({id:1,username:'zhangsan',age:20})
WriteResult({ "nInserted" : 1 })
> db.user.insert({id:2,username:'lisi',age:21})
WriteResult({ "nInserted" : 1 })
> db.user.insert({id:3,username:'wangwu',age:22})
WriteResult({ "nInserted" : 1 })
> db.user.insert({id:4,username:'zhaoliu',age:22})
WriteResult({ "nInserted" : 1 })
//查询所有数据
> db.user.find()
{ "_id" : ObjectId("67b735a36c674f9f2b6e0776"), "id" : 1, "username" : "zhangsan" }
{ "_id" : ObjectId("67b735c36c674f9f2b6e0777"), "id" : 2, "username" : "zhangsan", "sex" : "男" }
{ "_id" : ObjectId("67b73d806c674f9f2b6e0778"), "id" : 1, "username" : "zhangsan", "age" : 20 }
{ "_id" : ObjectId("67b73d806c674f9f2b6e0779"), "id" : 2, "username" : "lisi", "age" : 21 }
{ "_id" : ObjectId("67b73d806c674f9f2b6e077a"), "id" : 3, "username" : "wangwu", "age" : 22 }
{ "_id" : ObjectId("67b73d836c674f9f2b6e077b"), "id" : 4, "username" : "zhaoliu", "age" : 22 }
//使用pretty()方法,让数据更好阅读
> db.user.find().pretty()
{
"_id" : ObjectId("67b735a36c674f9f2b6e0776"),
"id" : 1,
"username" : "zhangsan"
}
{
"_id" : ObjectId("67b735c36c674f9f2b6e0777"),
"id" : 2,
"username" : "zhangsan",
"sex" : "男"
}
{
"_id" : ObjectId("67b73d806c674f9f2b6e0778"),
"id" : 1,
"username" : "zhangsan",
"age" : 20
}
{
"_id" : ObjectId("67b73d806c674f9f2b6e0779"),
"id" : 2,
"username" : "lisi",
"age" : 21
}
{
"_id" : ObjectId("67b73d806c674f9f2b6e077a"),
"id" : 3,
"username" : "wangwu",
"age" : 22
}
{
"_id" : ObjectId("67b73d836c674f9f2b6e077b"),
"id" : 4,
"username" : "zhaoliu",
"age" : 22
}
//在第二个{}里显示要返回的字段
> db.user.find({},{id:1,username:1})
{ "_id" : ObjectId("67b735a36c674f9f2b6e0776"), "id" : 1, "username" : "zhangsan" }
{ "_id" : ObjectId("67b735c36c674f9f2b6e0777"), "id" : 2, "username" : "zhangsan" }
{ "_id" : ObjectId("67b73d806c674f9f2b6e0778"), "id" : 1, "username" : "zhangsan" }
{ "_id" : ObjectId("67b73d806c674f9f2b6e0779"), "id" : 2, "username" : "lisi" }
{ "_id" : ObjectId("67b73d806c674f9f2b6e077a"), "id" : 3, "username" : "wangwu" }
{ "_id" : ObjectId("67b73d836c674f9f2b6e077b"), "id" : 4, "username" : "zhaoliu" }
//返回查询文档的个数
> db.user.find().count()
6
//等值查询id=1的文档数据
> db.user.find({id:1})
{ "_id" : ObjectId("67b735a36c674f9f2b6e0776"), "id" : 1, "username" : "zhangsan" }
{ "_id" : ObjectId("67b73d806c674f9f2b6e0778"), "id" : 1, "username" : "zhangsan", "age" : 20 }
//查询age<=21的数据
> db.user.find({age:{$lte:21}})
{ "_id" : ObjectId("67b73d806c674f9f2b6e0778"), "id" : 1, "username" : "zhangsan", "age" : 20 }
{ "_id" : ObjectId("67b73d806c674f9f2b6e0779"), "id" : 2, "username" : "lisi", "age" : 21 }
//and条件,查询age<=21且id>=2的数据,在第一个{}内使用,
> db.user.find({age:{lte:21}, id:{gte:2}})
{ "_id" : ObjectId("67b73d806c674f9f2b6e0779"), "id" : 2, "username" : "lisi", "age" : 21 }
//or条件,查询id等于1或者id=2的文档数据
> db.user.find({$or:[{id:1},{id:2}]})
{ "_id" : ObjectId("67b735a36c674f9f2b6e0776"), "id" : 1, "username" : "zhangsan" }
{ "_id" : ObjectId("67b735c36c674f9f2b6e0777"), "id" : 2, "username" : "zhangsan", "sex" : "男" }
{ "_id" : ObjectId("67b73d806c674f9f2b6e0778"), "id" : 1, "username" : "zhangsan", "age" : 20 }
{ "_id" : ObjectId("67b73d806c674f9f2b6e0779"), "id" : 2, "username" : "lisi", "age" : 21 }
//跳过1条数据,查询2条数据
> db.user.find().limit(2).skip(1)
{ "_id" : ObjectId("67b735c36c674f9f2b6e0777"), "id" : 2, "username" : "zhangsan", "sex" : "男" }
{ "_id" : ObjectId("67b73d806c674f9f2b6e0778"), "id" : 1, "username" : "zhangsan", "age" : 20 }
//按照age倒序排序,-1为倒序,1为正序
> db.user.find().sort({id:-1})
{ "_id" : ObjectId("67b73d836c674f9f2b6e077b"), "id" : 4, "username" : "zhaoliu", "age" : 22 }
{ "_id" : ObjectId("67b73d806c674f9f2b6e077a"), "id" : 3, "username" : "wangwu", "age" : 22 }
{ "_id" : ObjectId("67b735c36c674f9f2b6e0777"), "id" : 2, "username" : "zhangsan", "sex" : "男" }
{ "_id" : ObjectId("67b73d806c674f9f2b6e0779"), "id" : 2, "username" : "lisi", "age" : 21 }
{ "_id" : ObjectId("67b735a36c674f9f2b6e0776"), "id" : 1, "username" : "zhangsan" }
{ "_id" : ObjectId("67b73d806c674f9f2b6e0778"), "id" : 1, "username" : "zhangsan", "age" : 20 }
>
索引
索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。
MongoDB支持的索引类型有:
- 单字段索引(Single Field)
-
- 支持所有数据类型中的单个字段索引
- 复合索引(Compound Index)
-
- 基于多个字段的索引,创建复合索引时要注意字段顺序与索引方向
- 多键索引(Multikey indexes)
-
- 针对属性包含数组数据的情况,MongoDB支持针对数组中每一个element创建索引。
- 全文索引(Text Index)
-
- 支持任意属性值为string或string数组元素的索引查询。
- 注意:一个集合仅支持最多一个Text Index,中文分词不理想,推荐Elasticsearch。
- 地理空间索引(Geospatial Index)
-
- 2dsphere索引,用于存储和查找球面上的点
- 2d索引,用于存储和查找平面上的点
- 哈希索引(Hashed Index)
-
- 针对属性的哈希值进行索引查询,当要使用Hashed index时,MongoDB能够自动的计算hash值,无需程序计算hash值。
- hash index仅支持等于查询,不支持范围查询。
#单字段索引,1表示升序创建索引,-1表示降序创建索引
db.集合名.createIndex({"字段名":排序方式})
#添加2dsphere索引db.集合名.createIndex({"字段名":"2dsphere"})
#示例,创建user集合,其中username和loc字段设置索引db.user.insert({id:1,username:'zhangsan',age:20,loc:{type:"Point",coordinates:[116.343847,40.060539]}})
db.user.insert({id:2,username:'lisi',age:22,loc:{type:"Point",coordinates:[121.612112,31.034633]}})
db.user.createIndex({"username":1})
db.user.createIndex({"loc":"2dsphere"})
#查看索引db.user.getIndexes()
#查看索引大小,单位:字节db.user.totalIndexSize()
#删除索引db.user.dropIndex("loc_2dsphere")
#删除除了_id之外的索引db.user.dropIndexes()
地理空间索引的type可以是下列的类型:
- Point(坐标点),coordinates必须是单个位置
- MultiPoint(多个点),coordinates必须是位置数组
- LineString(线形),coordinates必须是两个或多个位置的数组
- MultiLineString(多行线形),coordinates必须是LineString坐标数组的数组
- Polygon(多边形),coordinates成员必须是 LinearRing 坐标数组的数组,必须是闭环,也就是第一个和最后一个坐标点要相同。
- MultiPolygon(多个多边形),coordinates成员必须是 Polygon 坐标数组的数组。
- GeometryCollection(几何集合),geometries是任何一个对象的集合。
使用mongoDB-ui -》studio-3t
下载
官方网址:The Professional Client, IDE and GUI for MongoDB | Studio 3T
连接服务端

输入url

新建链接,输入链接字符串:
mongodb://sl:123321@192.168.150.101:27017/admin
链接字符串的格式:
mongodb://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb][?options]]
点击测试连接
输入名字后点击保存

打开可视化命令行

可以直接选择返回数据的格式
