一文快速入门 MongoDB 、MongoDB 8.2 下载安装、增删改查操作、索引、SpringBoot整合 Spring Data MongoDB

大家好,我是此林。今天来分享快速入门 MongoDB 、MongoDB 8.2 下载安装、增删改查操作、索引、SpringBoot整合、Spring Data MongoDB等。

目录

[1. 概述](#1. 概述)

[2. 安装](#2. 安装)

[2.1. 本地部署](#2.1. 本地部署)

[2.2. Docker 部署](#2.2. Docker 部署)

[3. 基本概念](#3. 基本概念)

[4. MongoDB基本操作](#4. MongoDB基本操作)

[4.1. 数据库以及表的操作](#4.1. 数据库以及表的操作)

[4.2. 新增数据](#4.2. 新增数据)

[4.3. 更新数据](#4.3. 更新数据)

[4.4. 删除数据](#4.4. 删除数据)

[4.5. 查询数据](#4.5. 查询数据)

[5. 索引](#5. 索引)

[6. SpringBoot 整合 MongoDB](#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:

bash 复制代码
sudo apt-get install libcurl4 libgssapi-krb5-2 libldap2 libwrap0 libsasl2-2 libsasl2-modules libsasl2-modules-gssapi-mit openssl liblzma5

CentOS:

bash 复制代码
sudo yum install libcurl openssl xz-libs

Windows 系统直接跳过到下一步。

下载 tarball

安装所需的必备包后,从以下链接下载 MongoDB Community tgz tarball:

MongoDB 下载中心

  1. 在 Version 下拉列表中选择要下载的 MongoDB 版本。

  2. 在 Platform 下拉菜单中,选择操作系统的版本和架构。

  3. 在 Package 下拉菜单中,选择 tgz。

  4. 单击 Download(连接)。

设置PATH 环境变量

这个命令即把MongoDB server的bin目录复制到 /usr/local/bin 下,这样命令行就可以直接访问命令 mongo。/path/to/mongodb-server/bin/* 替换为你自己的 bin 路径。

bash 复制代码
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,这个更加简单。

bash 复制代码
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. 数据库以及表的操作

查看所有的数据库

bash 复制代码
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB

通过use关键字切换数据库

bash 复制代码
> use admin
switched to db admin

创建数据库

说明:在MongoDB中,数据库是自动创建的,通过use切换到新数据库中,进行插入数据即可自动创建数据库

bash 复制代码
> 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 #数据库自动创建

查看表

bash 复制代码
> show tables
user
> show collections
user

删除集合(表)

bash 复制代码
> db.user.drop()
true  #如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false。

删除数据库

bash 复制代码
> 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)。

bash 复制代码
# 插入数据

# 语法: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 }

更新不存在的数据,默认不会新增数据

bash 复制代码
> 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,就是新增数据

bash 复制代码
> 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()方法进行删除数据,语法如下:

bash 复制代码
db.collection.remove(
   <query>,
   {
     justOne: <boolean>,
     writeConcern: <document>
   }
)

参数说明:

  • query :(可选)删除的文档的条件。
  • justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
  • writeConcern :(可选)抛出异常的级别。
bash 复制代码
> 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:\}} | db.col.find({"likes":{lt:50}}).pretty() | where likes < 50 |
| 小于或等于 | {<key>:{lte:\}} | db.col.find({"likes":{lte:50}}).pretty() | where likes <= 50 |
| 大于 | {<key>:{gt:\}} | db.col.find({"likes":{gt:50}}).pretty() | where likes > 50 |
| 大于或等于 | {<key>:{gte:\}} | db.col.find({"likes":{gte:50}}).pretty() | where likes >= 50 |
| 不等于 | {<key>:{ne:\}} | db.col.find({"likes":{ne:50}}).pretty() | where likes != 50 |

bash 复制代码
#插入测试数据
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 支持的索引类型

  1. 单字段索引

    针对某一个字段建索引,最常用,查询速度快。

  2. 复合索引

    针对多个字段建索引,相当于"组合条件",字段顺序很重要。

  3. 多键索引

    当字段的值是数组时,可以对数组里的每个元素建索引,方便数组内元素查询。

  4. 全文索引

    可以对字符串内容建立索引,用于模糊搜索和关键字匹配。但中文分词效果不好,更推荐 Elasticsearch。

  5. 地理空间索引

    用于地理位置数据查询:

    • 2dsphere:球面坐标(经纬度查询)。

    • 2d:平面坐标。

  6. 哈希索引

    对字段的哈希值建立索引,适合做等值查询(比如 ID 精确查找),但不能做范围查询。

我们重点看【单字段索引】、【2dsphere索引】。

bash 复制代码
#单字段索引,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 依赖

XML 复制代码
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
    </dependencies>

2. 配置

XML 复制代码
spring:
  application:
    name: sl-express-mongodb
  data:
    mongodb:
      host: 192.168.150.101
      port: 27017
      database: test-db
      authentication-database: admin #认证数据库
      username: user1
      password: "123456"
      auto-index-creation: true #自动创建索引

在 Spring Boot 里配置 MongoDB 时,databaseauthentication-database 是两个不同的概念,容易混淆。

database,这是 实际要使用的业务数据库

authentication-database,这是MongoDB 认证用户信息存放的数据库

  • MongoDB 用户是存在某个数据库下的(默认是 admin 数据库)。

  • 当你连接 MongoDB 时,驱动需要先去 authentication-database 找这个用户的账号和密码,认证通过后,才允许你访问 database

3. Entity

Person.java

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

java 复制代码
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Document("address") //指定表名
public class Address {
    private String street;
    private String city;
    private String zip;
}

4. Service

java 复制代码
@Service
public class PersonServiceImpl implements PersonService {

    @Resource
    private MongoTemplate mongoTemplate;

    @Override
    public void savePerson(Person person) {
        this.mongoTemplate.save(person);
    }

    @Override
    public 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);
    }

    @Override
    public List<Person> queryPersonListByName(String name) {
        Query query = Query.query(Criteria.where("name").is(name)); //构造查询条件
        return this.mongoTemplate.find(query, Person.class);
    }

    @Override
    public 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);
    }

    @Override
    public void deleteById(String id) {
        Query query = Query.query(Criteria.where("id").is(new ObjectId(id)));
        this.mongoTemplate.remove(query, Person.class);
    }
}

5. 测试

java 复制代码
@SpringBootTest
class PersonServiceTest {

    @Resource
    PersonService personService;

    @Test
    void 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);
    }

    @Test
    void 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);
    }

    @Test
    void queryPersonListByName() {
        List<Person> personList = this.personService.queryPersonListByName("张三");
        personList.forEach(System.out::println);
    }

    @Test
    void queryPersonPageList() {
        List<Person> personList = this.personService.queryPersonPageList(1, 10);
        personList.forEach(System.out::println);
    }

    @Test
    void deleteById() {
        this.personService.deleteById("632283c08139e535c2bd7579");
    }
}

今天的分享就到这里了。

我是此林,关注我吧!带你看不一样的世界!

相关推荐
炬火初现3 小时前
SQL——子查询
数据库·sql
semantist@语校3 小时前
语校网500所里程碑:日本语言学校数据库的标准化与可追溯机制
大数据·数据库·人工智能·百度·语言模型·oracle·github
野犬寒鸦3 小时前
从零起步学习Redis || 第五章:利用Redis构造分布式全局唯一ID
java·服务器·数据库·redis·分布式·后端·缓存
yenggd3 小时前
QoS之流量整形配置方法
网络·数据库·华为
吹晚风吧3 小时前
SSE是什么?SSE解决什么问题?在什么场景使用SSE?
java·springboot·sse
陪你在童年4 小时前
EXCEL根据类别分页预览或者直接生成PDF
数据库
l1t4 小时前
在duckdb 1.4中编译和使用postgresql协议插件duckdb-pgwire
开发语言·数据库·c++·postgresql·插件·duckdb
武子康4 小时前
Java-138 深入浅出 MySQL Spring Boot 事务传播机制全解析:从 REQUIRED 到 NESTED 的实战详解 传播机制原理
java·大数据·数据库·spring boot·sql·mysql·事务
snpgroupcn4 小时前
SAP S/4HANA迁移方法选哪种?选择性数据转换是否合适?企业需要考虑哪些关键因素!
运维·数据库·云计算