表
基本操作库查看所有库1 2
| show databases; show dbs;
|
1 2 3 4
| > show dbs; admin 0.000GB config 0.000GB local 0.000GB
|
注意:
admin :从权限的角度来看,这是”root”数据库,要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器
local :这个数据库永远不会被复制,可以用来存储限于本地单台服务器的任意集合
config :当MongoDB用于分片设置时,config数据库在内部使用,用于保存分片的相关信息
创建数据库
1 2 3 4 5
| > use product switched to db product > db product >
|
use 代表创建并使用,当库中没有数据时默认不显示这个库
删除数据库
默认删除当前选中的库
集合查看库中所有集合1 2
| show collections; show tables;
|
创建集合1
| db.createCollection('集合名称', [options])
|
options可以是如下参数:
字段 |
类型 |
描述 |
capped |
布尔 |
(可选)如果为true,则创建固定集合,固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。当改值为true时,必须指定size参数 |
size |
数值 |
(可选)为固定集合指定一个最大值,即字节数,如果capped为true,也需要指定该字段 |
max |
数值 |
(可选)指定固定集合中包含文档的最大数量 |
注意:当集合不存在时,向集合中插入文档也会自动创建该集合
删除集合
文档插入文档单条文档1
| db.集合名称.insert({"name": "小明", "age": 23, "bir": "2001-01-01"})
|
多条文档1 2 3 4 5 6 7 8 9 10 11 12
| db.集合名称.insertMany( [<document 1>, <document 2>, ···], { writeConcern: 1, // 写入策略,默认为1,即要求确认写操作,0是不要求 ordered: true // 指定是否要按顺序写入,默认为true,按顺序写入 } )
db.集合名称.insert([ {"name": "小明", "age": 23, "bir": "2001-01-01"}, {"name": "小红", "age": 23, "bir": "2001-01-01"} ])
|
脚本方式1 2 3
| for(let i = 0; i < 100; i++){ db.集合名称.insert({"_id": i, "name": "小明_" + i, "age": 23}) }
|
注意:在MongoDB中每个文档都会有一个_id作为唯一标识,_id默认会自动生成,如果手动指定将使用手动指定的值作为_id的值
查询所有
删除文档1 2 3 4 5 6 7 8 9 10
| db.集合名称.remove( <query>, { justOne: <boolean>, writeConcern: <document> } ) // 删除所有 db.集合名称.remove({}) db.集合名称.remove(age:21)
|
参数说明:
- query:(可选)删除文档的条件
- justOne:(可选)如果设为true或1,则只删除一个文档,如果不设置该参数,或使用默认值false,则删除所有匹配条件的文档
- writeConcern:(可选)抛出异常的级别
更新文档1 2 3 4 5 6 7 8 9
| db.集合名称.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:可选,抛出异常的级别
1 2 3 4 5 6 7 8
| // 这个更新是将符合条件的第一条文档(除id外)全部更新为后面的文档,相当于先删除再更新 db.集合名称.update({"name": "张三", {"name": "李四", "bir": new date()}}) // 保留原来数据更新,但是只更新符合条件的第一条数据,如果原文档没有更新的字段,则在原文档基础上增加该字段 db.集合名称.update({"name": "小红", {$set: {"name": "明明"}}) // 保留原来数据更新,更新符合条件的所有数据 db.集合名称.update({"name": "小红", {$set: {"name": "小明"}}, {multi:true}) // 保留原来数据更新,更新符合条件的所有数据,没有条件符合时插入数据 db.集合名称.update({"name": "小红", {$set: {"name": "小明"}}, {multi:true, upsert: true})
|
文档查询MongoDB查询文档使用find()方法,find()方法以非结构化的方式来显示所有文档
1
| db.集合名称.find(query, projection)
|
如果你需要以易读的方式来读取数据,可以使用pretty()方法,语法格式如下:
对比语法如果你熟悉常规的SQL数据,通过下表可以更好的理解MongoDB的条件语句查询
操作 |
格式 |
范例 |
RDBMS中的类似语句 |
等于 |
{;} |
db.集合名称.find({“name”: “小明”}).pretty() |
where name = ‘小明’ |
小于 |
{;{$lt: }} |
db.集合名称.find({“age”: {$lt: 30}}).pretty() |
where age < 30 |
小于或等于 |
{;{$lte: }} |
db.集合名称.find({“age”: {$lte: 30}}).pretty() |
where age <= 30 |
大于 |
{;{$gt: }} |
db.集合名称.find({“age”: {$gt: 30}}).pretty() |
where age > 30 |
大于或等于 |
{;{$gte: }} |
db.集合名称.find({“age”: {$gte: 30}}).pretty() |
where age >= 30 |
不等于 |
{;{$ne: }} |
db.集合名称.find({“age”: {$ne: 30}}).pretty() |
where age != 30 |
AND1 2
| db.集合名称.find({key1: value1, key2: value2}).pretty() 在AND查询中,如果key1和key2是同一个字段,那么后一个查询条件会覆盖掉前一个查询条件
|
类似于 WHERE 语句:WHERE key1=value1 AND key2=value2
ORMongoDB OR条件语句使用了关键字$or,语法格式如下:
1 2 3 4 5 6 7
| db.集合名称.find( { $or: [ {key1: value1}, {key2: value2} ] } ).pretty()
|
类似于 WHERE 语句:WHERE key1=value1 or key2=value2
AND和OR联合类似SQL语句为:where age > 50 and (name = '小明' or name = '小红')
1
| db.集合名称.find({age: {$gt: 50}, $or: [{name: "小红"}, {name: "小红"}]}).pretty()
|
数组中查询1 2 3 4
| db.集合名称.insert({_id: 1, age: 23, likes: ["看书", "学习"], name: "小明"}) db.集合名称.find({likes: "看书"})
db.集合名称.find({likes: {$size:2}})
|
模糊查询类似SQL中:where name like '%name%'
1 2
| db.集合名称.find({name: /小/})
|
注意:在MongoDB中使用正则表达式可以实现近似模糊查询功能
排序1 2 3
| db.集合名称.find().sort({name: 1, age: 1})
|
类似SQL语句为:order by name, age
分页类似SQL语句:limit start, rows
1
| db.集合名称.find().sort({条件}).skip(start).limit(rows)
|
总条数类似于SQL语句:select count(id) from ···
1 2
| db.集合名称.count() db.集合名称.find({name: "小明"}).count()
|
去重
指定返回字段1 2
| db.集合名称.find({条件}, {name: 1, age: 1})
|
$type说明$type操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果
MongoDB中可以使用的部分类型如下表所示
类型 |
数字 |
备注 |
Double |
1 |
|
String |
2 |
|
Object |
3 |
|
Array |
4 |
|
Binary data |
5 |
|
Undefined |
6 |
已废弃 |
Object id |
7 |
|
Boolean |
8 |
|
Date |
9 |
|
1 2
| db.集合名称.find({name: {$type: 2}}).pretty() db.集合名称.find({name: {$type: "string"}}).pretty()
|
索引https://docs.mongodb.com/manual/indexes/
说明索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录,这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的,索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构
原理
从根本上说,MongoDB中的索引与其它数据库系统中的索引类似,MongoDB在集合层面上定义了索引,并支持对MongoDB集合中的任何字段或文档的子字段进行索引
操作创建索引1 2
| db.集合名称.createIndex(keys, options) db.集合名称.createIndex({"title": 1, "description": -1})
|
说明:语法中 Key 值为你要创建的索引字段,1 为指定按升序创建索引,-1为按降序创建索引
createIndex()接收可选参数,可选参数列表部分如下:
Parameter |
Type |
Description |
background |
Boolean |
创建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加”background”可选参数,”background”默认值为false |
unique |
Boolean |
建立的索引是否唯一,指定为true创建唯一索引,默认值为false |
name |
string |
索引的名称,如果未指定,MongoDB会通过连接缩印的字段名和排序顺序生成一个索引名称 |
expireAfterSeconds |
integer |
指定一个以秒为单位的数值,完成TTL设定,设定索引的生成时间 |
查看集合索引
查看集合索引大小1
| db.集合名称.totalIndexSize()
|
删除集合所有索引
删除集合指定索引1
| db.集合名称.dropIndex("索引名称")
|
复合索引说明一个索引的值是由多个key进行维护的索引称之为复合索引
1
| db.集合名称.createIndex({"title": 1, "description": -1})
|
注意:MongoDB中复合索引和传统关系型数据库一致都是左前缀原则
聚合说明MongoDB中聚合(aggregate)主要用于处理数据(如统计平均值、求和等),并返回计算后的数据结果,有点类似SQL语句中的count(*)
使用1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| { title: 'MongoDB Overview', description: 'MongoDB is no sql database', by_user: 'runoob.com', url: 'http://www.runoob.com', tags: ['mongodb', 'database', 'NoSQL'], likes: 100 }, { title: 'NoSQL Overview', description: 'NoSQL database is very fast', by_user: 'runoob.com', url: 'http://www.runoob.com', tags: ['mongodb', 'database', 'NoSQL'], likes: 10 }, { title: 'Neo4j Overview', description: 'Neo4j is no sql database', by_user: 'Neo4j', url: 'http://www.runoob.com', tags: ['mongodb', 'database', 'NoSQL'], likes: 750 }
|
现在我们通过以上集合计算每个作者所写的文章数,使用aggregate()计算结果如下:
1
| db.集合名称.aggregate([{$group :{_id: "$by_user", "sum_by_user": {$sum: 1}}}])
|
常见聚合表达式
表达式 |
描述 |
实例 |
$sum |
计算总和 |
db.集合名称.aggregate([{$group :{_id: “$by_user”, “sum_by_user”: {$sum: 1}}}]) |
$avg |
计算平均值 |
db.集合名称.aggregate([{$group :{_id: “$by_user”, “avg_by_likes”: {$avg: “$likes”}}}]) |
$min |
获取集合中所有文档对应值的最小值 |
db.集合名称.aggregate([{$group :{_id: “$by_user”, “min_by_likes”: {$avg: “$likes”}}}]) |
$max |
获取集合中所有文档对应值的最大值 |
db.集合名称.aggregate([{$group :{_id: “$by_user”, “max_by_likes”: {$avg: “$likes”}}}]) |
$push |
将值加入一个数组中,不会判断是否有重复的值 |
db.集合名称.aggregate([{$group :{_id: “$by_user”, “push_by_url”: {$push: “$url”}}}]) |
$addToSet |
将值加入一个数组中,会判断是否有重复的值 |
db.集合名称.aggregate([{$group :{_id: “$by_user”, “addToSet_by_url”: {$addToSet: “$url”}}}]) |
$first |
根据资源文档的排序获取第一个文档数据 |
db.集合名称.aggregate([{$group :{_id: “$by_user”, “first_url”: {$first: “$url”}}}]) |
$last |
根据资源文档的排序获取最后一个文档数据 |
db.集合名称.aggregate([{$group :{_id: “$by_user”, “last_url”: {$last: “$url”}}}]) |
副本集说明https://docs.mongodb.com/manual/replication/
MongoDB副本集(Replica Set)是有自动故障恢复功能的主从集群,有一个Primary节点和一个或多个Secondary节点组成,副本集没有固定的主节点,当主节点发生故障时整个集群会选举一个主节点为系统提供服务以保证系统的高可用
Automatic Failover自动故障转移机制:当主节点未与集合的其他成员通信超过配置的选举超时时间(默认为10秒)时,合格的辅助节点将调用选举以将自己提名为新的主节点,集群尝试完成新主节点的选举并恢复正常操作
SpringBoot整合MongoDBSpring Data Mongodb
和Spring Data Elasticsearch类似,Spring Data Mongodb是Spring提供的一种以Spring Data风格来操作数据存储的方式,它可以避免编写大量的样板代码
常用注解
- @Document:表示映射到Mongodb文档上的领域对象
- @Id:表示某个域的id
- @Indexed:表示某个字段为Mongodb的索引字段
Spring Data方式的数据操作添加pom.xml依赖1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency>
|
修改SpringBoot配置文件1 2 3 4 5 6
| spring: data: mongodb: host: 127.0.0.1 port: 27017 database: mall-test
|
添加会员浏览记录文档对象MemberReadHistory
文档对象的ID域添加@Id注解,需要检索的字段添加@Indexed注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
@Data @AllArgsConstructor @NoArgsConstructor @Document public class MemberReadHistory { @Id private String id; @Indexed private Long memberId; private String memberNickname; private String memberIcon; @Indexed private Long productId; private String productName; private String productPic; private String productSubTitle; private String productPrice; private Date createTime; }
|
添加MemberReadHistoryRepository接口用于操作Mongodb
继承MongoRepository接口,同时定义一个衍生查询方法
1 2 3 4 5 6 7 8
| public interface MemberReadHistoryRepository extends MongoRepository<MemberReadHistory, String> {
List<MemberReadHistory> findByMemberIdOrderByCreateTimeDesc(Long memberId); }
|
添加MemberReadHistoryService接口1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
public interface MemberReadHistoryService {
void create(MemberReadHistory memberReadHistory);
int delete(List<String> ids);
List<MemberReadHistory> list(Long memberId); }
|
1 2 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
| @Service public class MemberReadHistoryServiceImpl implements MemberReadHistoryService { @Resource private MemberReadHistoryRepository memberReadHistoryRepository;
@Override public void create(MemberReadHistory memberReadHistory) { memberReadHistory.setId(null); memberReadHistory.setCreateTime(new Date()); memberReadHistoryRepository.save(memberReadHistory); }
@Override public int delete(List<String> ids) { List<MemberReadHistory> deleteList = ids.stream().map(id -> { MemberReadHistory memberReadHistory = new MemberReadHistory(); memberReadHistory.setId(id); return memberReadHistory; }).collect(Collectors.toList()); memberReadHistoryRepository.deleteAll(deleteList); return ids.size(); }
@Override public List<MemberReadHistory> list(Long memberId) { return memberReadHistoryRepository.findByMemberIdOrderByCreateTimeDesc(memberId); } }
|
|