一文快速入门 MongoDB 、MongoDB 8.2 下载安装、增删改查操作、索引、SpringBoot整合 Spring Data MongoDB
大家好,我是此林。今天来分享快速入门 MongoDB 、MongoDB 8.2 下载安装、增删改查操作、索引、SpringBoot整合、Spring Data MongoDB等。
目录
1. 概述
2. 安装
2.1. 本地部署
2.2. Docker 部署
3. 基本概念
4. MongoDB基本操作
4.1. 数据库以及表的操作
4.2. 新增数据
4.3. 更新数据
4.4. 删除数据
4.5. 查询数据
5. 索引
6. SpringBoot 整合 MongoDB
1. 概述
MongoDB 是一种新型的 NoSQL 数据库,它和我们常见的 MySQL、Oracle 这些关系型数据库有点像,但又更灵活。
它不是用一张张有固定行和列的表来存数据,而是用一种类似 JSON 的格式(叫 BSON)来保存信息。这样一来,数据可以随意增加字段,结构也可以很复杂,比如可以在一条记录里直接放数组、对象,甚至嵌套更多数据,非常适合应对互联网应用里多变的数据需求。
和传统数据库相比,MongoDB 最大的特点就是灵活、好扩展。不需要提前设计好死板的表结构,且支持索引。MongoDB的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现了类似关系数据库单表查询的绝大部分功能(可以通过聚合的方式实现多表查询),而且还支持对数据建立索引。
此外,MongoDB 本身就是为大规模应用设计的,它可以分布式部署,把数据分散到不同的服务器上,同时还能保证数据安全和高可用,所以特别适合用在电商、社交网络、日志收集、物联网等需要处理海量数据的场景。
2. 安装
MongoDB 提供两种服务器版本:社区版和企业版。
我们选择社区版。
2.1. 本地部署
安装 MongoDB Community Edition
使用以下命令安装 MongoDB Community Edition .tgz
Tarball 所需的依赖项:
Ubuntu:
sudo apt-get install libcurl4 libgssapi-krb5-2 libldap2 libwrap0 libsasl2-2 libsasl2-modules libsasl2-modules-gssapi-mit openssl liblzma5
CentOS:
sudo yum install libcurl openssl xz-libs
Windows 系统直接跳过到下一步。
下载 tarball。
安装所需的必备包后,从以下链接下载 MongoDB Community tgz
tarball:
➤ MongoDB 下载中心
-
在 Version 下拉列表中选择要下载的 MongoDB 版本。
-
在 Platform 下拉菜单中,选择操作系统的版本和架构。
-
在 Package 下拉菜单中,选择 tgz。
-
单击 Download(连接)。
设置PATH
环境变量
这个命令即把MongoDB server的bin目录复制到 /usr/local/bin 下,这样命令行就可以直接访问命令 mongo。/path/to/mongodb-server/bin/* 替换为你自己的 bin 路径。
sudo cp /path/to/mongodb-server/bin/* /usr/local/bin/
安装 MongoDB Shell (mongosh
)。
安装mongosh
,然后使用 MongoDB Shell 连接部署。刚刚我们只安装了 MongoDB 服务端,这个是我们的客户端,用户连接服务端。
Try MongoDB Tools - Download Free Here | MongoDB
第一个是命令行 client,第二个包含GUI界面。
初学建议第二个。
2.2. Docker 部署
推荐使用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#进入容器进行设置
docker exec -it mongodb /bin/bash
#进行认证
mongo -u "sl" -p "123321" --authenticationDatabase "admin"#测试命令,查看已有数据库
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
3. 基本概念
为了更好的理解,下面与SQL中的概念进行对比:
SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table joins | 表连接,MongoDB不支持 | |
primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |
4. MongoDB基本操作
4.1. 数据库以及表的操作
查看所有的数据库
> 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
4.2. 新增数据
在MongoDB中,存储的文档结构是一种类似于json的结构,称之为bson(全称为:Binary JSON)。
# 插入数据# 语法:db.COLLECTION_NAME.insert(document)> db.user.insert({id:1,username:'zhangsan',age:20})
WriteResult({ "nInserted" : 1 })> db.user.save({id:2,username:'lisi',age:25})
WriteResult({ "nInserted" : 1 })> db.user.find() #查询数据
{ "_id" : ObjectId("5c08c0024b318926e0c1f6dc"), "id" : 1, "username" : "zhangsan", "age" : 20 }
{ "_id" : ObjectId("5c08c0134b318926e0c1f6dd"), "id" : 2, "username" : "lisi", "age" : 25 }
在 MongoDB 里,每条数据都会有一个
_id
字段,相当于主键 ID,用来唯一标识这条数据。默认情况下,_id
的类型是 ObjectID。这个编号有 12 个字节,里面包含了:
时间信息(记录什么时候生成的)
机器标识(在哪台电脑上生成的)
进程号(是哪一个 MongoDB 进程生成的)
计数器(保证同一时间生成的 ID 也不重复)
这样设计的好处是:自动生成、全球唯一,不会冲突。
4.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 :可选,抛出异常的级别。
更新 age 字段:
> db.user.find()
{ "_id" : ObjectId("5c08c0024b318926e0c1f6dc"), "id" : 1, "username" : "zhangsan", "age" : 20 }
{ "_id" : ObjectId("5c08c0134b318926e0c1f6dd"), "id" : 2, "username" : "lisi", "age" : 25 }> 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 }
注意:如果这样写,会删除掉其他的字段
> 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 }
4.4. 删除数据
通过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({}) #删除所有数据
4.5. 查询数据
MongoDB 查询数据的语法格式为:db.user.find([query],[fields])
- query :可选,使用查询操作符指定查询条件
- fields :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式为:db.collection.find().pretty()
条件查询:
操作 | 格式 | 美观输出 | RDBMS中的类似语句 |
等于 | {<key>:<value>} | db.col.find({"by":"小李"}).pretty() | where by = '小李' |
小于 | {<key>:{$lt:<value>}} | db.col.find({"likes":{$lt:50}}).pretty() | where likes < 50 |
小于或等于 | {<key>:{$lte:<value>}} | db.col.find({"likes":{$lte:50}}).pretty() | where likes <= 50 |
大于 | {<key>:{$gt:<value>}} | db.col.find({"likes":{$gt:50}}).pretty() | where likes > 50 |
大于或等于 | {<key>:{$gte:<value>}} | db.col.find({"likes":{$gte:50}}).pretty() | where likes >= 50 |
不等于 | {<key>:{$ne:<value>}} | db.col.find({"likes":{$ne:50}}).pretty() | where likes != 50 |
#插入测试数据
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.find() #查询全部数据
db.user.find({},{id:1,username:1}) #只查询id与username字段
db.user.find().count() #查询数据条数
db.user.find({id:1}) #查询id为1的数据
db.user.find({age:{$lte:21}}) #查询小于等于21的数据
db.user.find({age:{$lte:21}, id:{$gte:2}}) #and查询,age小于等于21并且id大于等于2
db.user.find({$or:[{id:1},{id:2}]}) #查询id=1 or id=2#分页查询:Skip()跳过几条,limit()查询条数
#跳过1条数据,查询2条数据
db.user.find().limit(2).skip(1)
#按照age倒序排序,-1为倒序,1为正序
db.user.find().sort({id:-1})
5. 索引
MongoDB 索引和 MySQL 很相似。
MongoDB 支持的索引类型
-
单字段索引
针对某一个字段建索引,最常用,查询速度快。 -
复合索引
针对多个字段建索引,相当于“组合条件”,字段顺序很重要。 -
多键索引
当字段的值是数组时,可以对数组里的每个元素建索引,方便数组内元素查询。 -
全文索引
可以对字符串内容建立索引,用于模糊搜索和关键字匹配。但中文分词效果不好,更推荐 Elasticsearch。 -
地理空间索引
用于地理位置数据查询:-
2dsphere
:球面坐标(经纬度查询)。 -
2d
:平面坐标。
-
-
哈希索引
对字段的哈希值建立索引,适合做等值查询(比如 ID 精确查找),但不能做范围查询。
我们重点看【单字段索引】、【2dsphere索引】。
#单字段索引,1表示升序创建索引,-1表示降序创建索引
db.集合名.createIndex({"字段名":排序方式})#2dsphere索引
db.集合名.createIndex({"字段名":"2dsphere"})#示例,创建user集合,其中username和loc字段设置索引
db.user.createIndex({"username":1})
db.user.createIndex({"loc":"2dsphere"})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.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是任何一个对象的集合。
6. SpringBoot 整合 MongoDB
spring-data对MongoDB做了支持,使用spring-data-mongodb可以简化MongoDB的操作。
Spring Data MongoDB
1. 引入 maven 依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency></dependencies>
2. 配置
spring:application:name: sl-express-mongodbdata:mongodb:host: 192.168.150.101port: 27017database: test-dbauthentication-database: admin #认证数据库username: user1password: "123456"auto-index-creation: true #自动创建索引
在 Spring Boot 里配置 MongoDB 时,database
和 authentication-database
是两个不同的概念,容易混淆。
database
,这是 实际要使用的业务数据库。
authentication-database
,这是MongoDB 认证用户信息存放的数据库。
MongoDB 用户是存在某个数据库下的(默认是
admin
数据库)。当你连接 MongoDB 时,驱动需要先去
authentication-database
找这个用户的账号和密码,认证通过后,才允许你访问database
。
3. Entity
Person.java
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Document("person") //指定表名
public class Person {@Id // 标识为主键private ObjectId id;@Indexed //标识索引字段private String name;private int age;/*** 用户位置* x: 经度,y:纬度*/@GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)private GeoJsonPoint location;//存储嵌套对象数据private Address address;
}
Address.java
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Document("address") //指定表名
public class Address {private String street;private String city;private String zip;
}
4. Service
@Service
public class PersonServiceImpl implements PersonService {@Resourceprivate MongoTemplate mongoTemplate;@Overridepublic void savePerson(Person person) {this.mongoTemplate.save(person);}@Overridepublic void update(Person person) {//条件Query query = Query.query(Criteria.where("id").is(person.getId()));//更新的数据Update update = Update.update("age", person.getAge()).set("name", person.getName()).set("location", person.getLocation()).set("address", person.getAddress());//更新数据this.mongoTemplate.updateFirst(query, update, Person.class);}@Overridepublic List<Person> queryPersonListByName(String name) {Query query = Query.query(Criteria.where("name").is(name)); //构造查询条件return this.mongoTemplate.find(query, Person.class);}@Overridepublic List<Person> queryPersonPageList(int page, int pageSize) {PageRequest pageRequest = PageRequest.of(page - 1, pageSize);Query query = new Query().with(pageRequest);return this.mongoTemplate.find(query, Person.class);}@Overridepublic void deleteById(String id) {Query query = Query.query(Criteria.where("id").is(new ObjectId(id)));this.mongoTemplate.remove(query, Person.class);}
}
5. 测试
@SpringBootTest
class PersonServiceTest {@ResourcePersonService personService;@Testvoid savePerson() {Person person = Person.builder().id(ObjectId.get()).name("张三").age(20).location(new GeoJsonPoint(116.343847, 40.060539)).address(new Address("人民路", "上海市", "666666")).build();this.personService.savePerson(person);}@Testvoid update() {Person person = Person.builder().id(new ObjectId("632283c08139e535c2bd7579")).name("张三").age(22) //修改数据.location(new GeoJsonPoint(116.343847, 40.060539)).address(new Address("人民路", "上海市", "666666")).build();this.personService.update(person);}@Testvoid queryPersonListByName() {List<Person> personList = this.personService.queryPersonListByName("张三");personList.forEach(System.out::println);}@Testvoid queryPersonPageList() {List<Person> personList = this.personService.queryPersonPageList(1, 10);personList.forEach(System.out::println);}@Testvoid deleteById() {this.personService.deleteById("632283c08139e535c2bd7579");}
}
今天的分享就到这里了。
我是此林,关注我吧!带你看不一样的世界!