简介
MongoDB 是一个基于分布式文件存储的数据库,由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。是非关系型数据库中功能最丰富,最像关系数据库的。支持数据结构类似 json 的 bson 格式。可以存储比较复杂的数据类型。MongoDB 的查询语言非常强大,类似面向对象的查询语言,几乎可以实现类似数据库单表查询的绝大部分功能,支持对数据建立索引。
高性能(相比关系型数据库),易部署,易使用。

对事务要求不高的业务都能被 MongoDB 取代。分片实现高可用,内部采用轮询的方式进行数据存储。
下载安装
下载安装
数据库结构
数据库存储使用的是集合,集合中存储的是文档,即树状结构数据。

MongoDB 默认端口 27017
在线文档教程
语法
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | show dbs: 查询所有数据库 use 数据库名: 创建并且选中数据库,数据库已经存在则直接选中
 db: 查询当前选择的数据库
 db.dropDatabase(): 删除当前选中的数据库
 show collections: 查询当前库中的集合
 db.createCollection("集合名"): 创建集合
 db.集合名.drop(): 删除集合
 
 注意: db.集合名 == db.getCollection("集合名")
 
 | 
数据类型
支持的数据类型:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | String(字符串): mongodb中的字符串是UTF-8有效的 Integer(整数): 存储数值。整数可以是32位或64位,具体取决于您的服务器
 Boolean(布尔): 存储布尔(true/false)值
 Double(双精度): 存储浮点值
 Arrays(数组): 将数组或列表或多个值存储到⼀个键中
 Timestamp(时间戳): 存储时间戳
 Object(对象): 嵌⼊式⽂档
 Null (空值): 存储Null值
 Symbol(符号): 与字符串相同,⽤于具有特定符号类型的语⾔
 Date(⽇期): 以UNIX时间格式存储当前⽇期或时间
 Object ID(对象ID) : 存储⽂档ID
 Binary data(⼆进制数据): 存储⼆进制数据
 Code(代码): 将JavaScript代码存储到⽂档中
 Regular expression(正则表达式): 存储正则表达式
 
 | 
新增操作
往集合中新增文档,当集合不存在时,会自动先创建集合,再往集合中添加文档。
| 12
 
 | db.集合名.insert(文档)db.集合名.find() 查询集合中所有文档
 
 | 
操作成功时,会给文档生成一个_id 字段,就是文档的主键。
| 12
 3
 
 | // 插入一个员工对象db.users.insert({id: NumberLong(1), name: "小妖", age: NumberInt(18)})
 db.users.insert({id: 2, name: "bunny", age: 20})
 
 | 
注意,直接写数字默认是 Double 类型。
更新操作
语法
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | db.集合名.update(<query>,
 <update>,
 {
 upsert: <boolean>,
 multi: <boolean>,
 writeConcern: <document>
 }
 )
 
 简化方法:
 更新1个:db.集合名.updateOne( ... )
 更新所有:db.集合名.updateMany( ... )
 
 | 
参数:
- query: update 查询条件,类似 sql update查询 where 后面的条件
- update: update 的对象和一些更新的操作符(如$, $inc) 等,也可以理解为 sql update 查询,set 后面的
- upsert: 可选,这个参数的意思是,如果不存在update 的记录,是否插入 objNew,true 为插入,默认是 false,不插入。
- multi: 可选,mongodb 默认是 false,只更新找到的第一条记录,如果参数为 true,就把按调价查出来多条记录全部更新。
- writeConcern: 可选,抛出异常的级别
实例
| 12
 3
 4
 5
 
 | //把一个带有name=逍遥的文档,修改其age值为30 db.employees.updateOne({name: "逍遥"}, {$set: {age: 30}})
 
 //修改所有name=逍遥的文档,修改其name=bunny,age=20
 db.employees.updateMany({name: "逍遥"}, {$set: {name: "bunny", age: 30}})
 
 | 
删除操作
语法
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | db.集合名.remove(<query>,
 {
 justOne: <boolean>,
 writeConcern: <document>
 }
 )
 
 简化方法:
 删除1个:db.集合名.deleteOne( ... )
 删除所有:db.集合名.deleteMany( ... )
 
 | 
- query :(可选)删除的文档的条件。 
- justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除 所有匹配条件的文档。 
- writeConcern :(可选)抛出异常的级别
实例
| 12
 3
 4
 5
 6
 7
 8
 
 | // 删除 _id=xxx 的文档db.users.deleteOne({_id: objectId("xxx")})
 
 // 删除所有带有 name=bunny 的文档
 db.users.deleteMany({name: "bunny"})
 
 // 删除当前数据库中所有文档
 db.users.deleteMany()
 
 | 
查询操作
语法
db.集合名.find(query, projection)
- query: 可选,使用查询操作符指定查询条件
- projection: 可选,使用投影操作符指定返回的键。查询时返回文档中所有键值,只需省略该参数即可(默认省略)
实例
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | // 查询所有文档db.users.find()
 // 排序查询
 db.users.find().sort({字段: 1}) -> 按照字段升序排列
 db.users.find().sort({字段: -1}) -> 按照字段降序排列
 // 分页查询
 sikp(num): 跳过 num 个文档,相当于 start
 limit(num): 限制显示 num 个文档,相当于 pageSize
 
 db.users.find().skip(num).limit(num)
 需求:按年龄降序排列,查询第二页,每页显示3个
 
 | 
高级查询
等值查询
find({字段: 值})
比较查询
find({字段: {比较操作符: 值, ...}})
- 大于(>) -> $gt
- 小于(<) -> $lt
- 大于等于(>=) -> $gte
- 小于等于(<=) -> $lte
- 不等于(!=) -> $ne
- 集合运算 -> $in,{name: {$in:["xiaoyao", "bunny"]}}
- 判断存在 -> $exists,{name: {$exists: true}}
逻辑查询:
- && -> $and
- || -> $or
- ! -> $not
模糊查询
MongoDB 的模糊查询使用的是正则表达式语法 {name: {$regex:/^.*keyword.*$/}},实际上 MongoDB 也是不擅长执行模糊查询的,在实际开发中不使用。
设置用户
用户设置
在 MongoDB 的配置文件:安装目录/Server/bin/mongod.cfg 中,如果修改了以下配置
| 12
 3
 
 | # 在29行位置,配置开启权限认证security:
 authorization: enabled
 
 | 
如果完成了上述配置,重启服务器后,登录时需要输入密码,否则不能执行任何命令。
Spring Data MongoDB
准备工作
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 
 | <packaging>jar</packaging>
 <parent>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-parent</artifactId>
 <version>2.1.3.RELEASE</version>
 </parent>
 
 <dependencies>
 
 <dependency>
 <groupId>org.projectlombok</groupId>
 <artifactId>lombok</artifactId>
 <version>1.16.6</version>
 <scope>provided</scope>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter</artifactId>
 </dependency>
 
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-test</artifactId>
 </dependency>
 
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-data-mongodb</artifactId>
 </dependency>
 </dependencies>
 
 
 <build>
 <plugins>
 
 <plugin>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-maven-plugin</artifactId>
 </plugin>
 </plugins>
 </build>
 
 | 
配置连接参数
application.properties
| 12
 3
 4
 5
 6
 7
 
 | 
 
 spring.data.mongodb.uri=mongodb://root:admin@localhost/mongotest?authSource=admin
 
 
 logging.level.org.springframework.data.mongodb.core=debug
 
 | 
操作数据库方案
使用,在 MongoDB 中提供了2个方案操作数据库。
高度封装的方案: MongoRepository
可以自定义配置方案:MongoTemplate
MongoRepository
该接口对 MongoDB 数据的常用操作进行了封装,只需要写个接口继承该接口就能直接拥有 CRUD 的基本操作,学习 JPA 的方法命名规范,可以完成各种复杂的高级操作,底层会调用 MongoTemplate 方法。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | 
 
 
 
 
 @Repository
 public interface UserMongoRepository extends MongoRepository<User, ObjectId> {
 
 List<User> findByName(String name);
 }
 
 | 
创建接口,放在 respository 包下。使用 Spring-data 的技术,都推荐放在 respository 包下。
需要配置 domain 类
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | @NoArgsConstructor@Setter
 @Getter
 @ToString
 @Document("users")
 public class User extends BaseDomain {
 @Id
 private ObjectId _id;
 
 private String name;
 private Integer age;
 @DateTimeFormat
 private Date bornDate;
 private String headImg;
 }
 
 | 
增删改
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | @Testpublic void testSaveOrUpdate() {
 System.out.println(repository);
 User user = new User();
 user.setName("lz");
 user.setAge(19);
 System.out.println(user);
 
 repository.save(user);
 System.out.println(user);
 
 }
 
 | 
如果配置了 id,调用 save 方法就是修改操作。
日志如下
| 12
 3
 4
 5
 6
 
 | 2019-10-08 16:46:22.062 DEBUG 2584 --- [           main] o.s.data.mongodb.core.MongoTemplate      : Inserting Document containing fields: [name, age, _class] in collection: users2019-10-08 16:46:22.107  INFO 2584 --- [           main] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:2, serverValue:10}] to 127.0.0.1:27017
 
 
 2019-10-08 16:54:58.307 DEBUG 2636 --- [           main] o.s.data.mongodb.core.MongoTemplate      : Saving Document containing fields: [_id, name, age, _class]
 2019-10-08 16:54:58.342  INFO 2636 --- [           main] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:2, serverValue:12}] to 127.0.0.1:27017
 
 | 
inserting 新增,saving 更新,removing 删除
查询:查多个
| 12
 3
 4
 5
 
 | @Testpublic void testQuery() {
 List<User> list = repository.findAll();
 list.forEach(System.out::println);
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 
 | 
 
 
 
 
 Page<User> page = repository.findAll(PageRequest.of(0, 3));
 page.getContent().forEach(System.out::println);
 
 | 
| 12
 3
 4
 5
 
 | @Testpublic void testget() {
 Optional<User> byId = repository.findById(new ObjectId("5d9c4cde8670510a18497809"));
 byId.ifPresent(System.out::println);
 }
 
 | 
JPA 方法命名规范
只要符合 JPA 方法命名规范,不需要写方法实现。
| 关键字 | 例子 | JPQL | 
| And | findByNameAndAge(String name, Integer age) | where name = ? and age = ? | 
| Or | findByNameOrAge(String name, Integer age) | where name = ? or age = ? | 
| Is | findByName(String name) | where name = ? | 
| Between | findByAgeBetween(Integer min, Integer max) | where age between ? and ? | 
| LessThan | findByAgeLessThan(Integer age) | where age < ? | 
| LessThanEqual | findByIdLessThanEqual | where id <= ? | 
| GreaterThan | findByIdGreaterThan | where id > ? | 
| GreaterThanEqual | findByIdGreaterThanEqual | where id > = ? | 
| After | findByIdAfter | where id > ? | 
| Before | findByIdBefore | where id < ? | 
| IsNull | findByNameIsNull | where name is null | 
| isNotNull,NotNull | findByNameNotNull | where name is not null | 
| Like | findByNameLike | where name like ? | 
| NotLike | findByNameNotLike | where name not like ? | 
| StartingWith | findByNameStartingWith | where name like ‘?%’ | 
| EndingWith | findByNameEndingWith | where name like ‘%?’ | 
| Containing | findByNameContaining | where name like ‘%?%’ | 
| OrderBy | findByIdOrderByXDesc | where id=? order by x desc | 
| Not | findByNameNot | where name <> ? | 
| In | findByIdIn(Collection<?> c) | where id in (?) | 
| NotIn | findByIdNotIn(Collection<?> c) | where id not  in (?) | 
| True | findByAaaTue | where aaa = true | 
| False | findByAaaFalse | where aaa = false | 
| IgnoreCase | findByNameIgnoreCase | where UPPER(name)=UPPER(?) | 
MongoTemplate
SpringBoot 完成了自动配置,直接注入即可。依靠该对象可以完成任何 MongoDB 操作,一般和 MongoRepository 分工合作,多数用于复杂的高级查询以及底层操作。
| 12
 
 | @Autowiredprivate MongoTemplate template;
 
 | 
| 12
 
 | List<T> mongoTemplate.find(Query query, Class<T> type, String collectionName);
 
 | 
条件封装 Query
| 12
 3
 4
 5
 6
 7
 
 | Criteria.where(String key).is(Object val);
 Criteria.orOperator(Criteria...);
 
 
 Criteria.where(String key).regex(String regex);
 
 
 | 
最后通过 addCriteria 把条件封装到 Query 对象中
| 12
 
 | Query对象.addCriteria(Criteria criteria); Query对象.skip(start).limit(pageSize);
 
 | 
实例代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 
 | @Autowiredprivate MongoTemplate mongoTemplate;
 
 
 public void testQuery1() throws Exception {
 
 
 Query query = new Query();
 
 query.skip(3).limit(3);
 
 query.with(new Sort(Sort.Direction.ASC, "id"));
 
 List<User> list = mongoTemplate.find(query, User.class, "users");
 list.forEach(System.err::println);
 
 }
 
 
 @Test
 public void testQuery2() throws Exception {
 
 
 Criteria criteria = Criteria.where("name").is("bunny");
 
 Query query = new Query();
 query.addCriteria(criteria);
 
 List<User> list = mongoTemplate.find(query, User.class, "users");
 list.forEach(System.err::println);
 
 }
 
 
 @Test
 public void testQuery3() throws Exception {
 
 
 Criteria criteria = new Criteria().orOperator(
 
 Criteria.where("name").is("bunny"),
 
 Criteria.where("age").lt(30));
 
 
 Query query = new Query();
 
 query.addCriteria(criteria);
 
 List<User> list = mongoTemplate.find(query, User.class, "users");
 list.forEach(System.err::println);
 
 }
 
 
 @Test
 public void testQuery4() throws Exception {
 
 Criteria criteria = new Criteria().andOperator(Criteria.where("name").regex(".*wang.*"), Criteria.where("age").gte(30).lte(32));
 
 Query query = new Query();
 
 query.addCriteria(criteria);
 
 List<User> list = mongoTemplate.find(query, User.class, "users");
 list.forEach(System.err::println);
 }
 
 |