简介
- 百度百科
MongoDB是一个基于分布式文件存储的数据库
(支持集群、分片处理)。由C++语言编写。旨在为WEB应用提供可扩展高性能的数据存储解决方案
。
MongoDB是一个介于关系数据库和非关系数据库之间的产品(偏向于非关系型数据库NoSQL),是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式(对json进行扩展),因此可以存储比较复杂的数据类型。MongoDB最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引.
总结: mongoDB是一个非关系型文档数据库。
特点
- 面向集合存储,易存储对象类型的数据
- 支持查询以及动态查询
- 支持RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言
- 文件存储格式为BSON(一种JSON的扩展)
- 支持复制和故障恢复和分片
- 支持事务支持(要求性不高,不能完全取代关系型数据库)
- 索引、聚合、关联....
应用场景
- 游戏应用:使用云数据库MongoDB作为游戏服务器的数据库存储用户信息。用户的游戏装备、积分等直接以内嵌文档的形式存储,方便进行查询与更新。
- 物流应用:使用云数据库MongoDB存储订单信息,订单状态在运送过程中会不断更新,以云数据库MongoDB内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来,方便快捷且一目了然。
- 社交应用:使用云数据库MongoDB存储用户信息以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能。并且,云数据库MongoDB非常适合用来存储聊天记录,因为它提供了非常丰富的查询,并在写入和读取方面都相对较快。
- 视频直播:使用云数据库MongoDB存储用户信息、礼物信息等。
- 大数据应用:使用云数据库MongoDB作为大数据的云存储系统,随时进行数据提取分析,掌握行业动态。
安装
# 1.拉取 mongodb 镜像
- docker pull mongo:5.0.5
# 2.运行 mongo 镜像
- docker run -d --name mongo -p 27017:27017 mongo:5.0.5
# 3.进入 mongo 容器
- docker exec -it 0935 bash
核心概念
库<DataBase>
mongodb中的库就类似于传统关系型数据库中库的概念,用来通过不同库隔离不同应用数据。
mongodb中可以建立多个数据库。每一个库都有自己的集合和权限,不同的数据库也放置在不同的文件中。默认的数据库为"test",数据库存储在启动指定的data目录中。
集合<Collection>
集合就是 MongoDB 文档组,类似于 RDBMS (关系数据库管理系统:Relational Database Management System)中的表的概念
。
集合存在于数据库中,一个库中可以创建多个集合。每个集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。
文档<Document>
文档集合中一条条记录,是一组键值(key-value)对(即 BSON)。MongoDB 的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是 MongoDB 非常突出的特点。
一个简单的文档例子如下:
{"site":"www.baidu.com", "name":"xiaowu"}
关系总结
基本操作
库<database>
- 查看所有库
show databases; | show dbs;
注意:
- admin: 从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
- local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合。
- config: 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息
- 创建数据库
use 库名
注意: use 代表创建并使用,当库中没有数据时默认不显示这个库
。
- 删除数据库
默认删除当前选中的库
db.dropDatabase() ---注意此处有括号
- 查看当前所在库
db;
集合<Collection>
- 查看库中所有集合
show collections; | show tables;
- 创建集合
db.createCollection('集合名称', [options])
options可以是如下参数:
注意:当集合不存在时,向集合中插入文档也会自动创建该集合。
- 删除集合
db.集合名称.drop();
-- 如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false。
文档<document>
参考文档: mongosh Methods — MongoDB Manual
- 插入文档
单条文档
db.集合名称.insert({"name":"不良人","age":23,"bir":"2012-12-12"})
多条文档
db.collection.insertMany():向指定集合中插入多条文档数据【推荐使用】
db.集合名称.insertMany(
[ <document 1> , <document 2>, ... ],
{
writeConcern: 1,//写入策略,默认为1,即要求确认写操作,0是不要求。
ordered: true //指定是否按顺序写入,默认true,按顺序写入。
}
)
db.集合名称.insert([
{"name":"不良人","age":23,"bir":"2012-12-12"},
{"name":"小黑","age":25,"bir":"2012-12-12"}
]);
脚本方式
for(let i=0;i<100;i++){
db.users.insert({"_id":i,"name":"不良人_"+i,"age":23});
}
注意:在mongodb中每个文档都会有一个_id作为唯一标识,_id默认会自动生成,如果手动指定将使用手动指定的值作为_id 的值。
- 查询所有
db.集合名称.find();
- 删除文档
db.集合名称.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)
由于remove()方法已经过时了,现在官方推荐使用deleteOne()和deleteMany()方法。
db.集合名称.deleteMany({query}) -- 不指定条件时删除集合下全部文档
db.users.deleteMany({});
db.users.deleteMany({age:23});
db.集合名称.deleteOne({query}) -- 删除一条文档
db.users.deleteOne({_id:ObjectId("64108c960d0d9fdb638f66d0")});
参数说明:
- query :
可选
删除的文档的条件。 - justOne :
可选
如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。 - writeConcern :
可选
抛出异常的级别
注意:文档内容全部删除后,文档仍存在,即删除内容,不删除结构。
- 更新文档
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 :可选,抛出异常的级别。
db.集合名称.update({"name":"zhangsan"},{name:"11",bir:new date()})
这个更新是将符合条件的全部更新成后面的文档,相当于先删除在更新
db.集合名称.update({"name":"xiaohei"},{$set:{name:"mingming}})
保留原来数据更新,但是只更新符合条件的第一条数据
db.集合名称.update({name:"小黑"},{$set:{name:"小明”}},{multi:true})
保留原来数据更新,更新符合条件的所有数据
db.集合名称.update({name:"小黑"},{$set:{name:"小明”}},(multi:true,upsert:true}
保留原来数据更新,更新符合条件的所有数据 没有条件符合时插入数据
在3.2版本开始,MongoDB提供以下更新集合文档的方法:
db.collection.updateOne():向指定集合更新单个文档
db.users.updateOne({"_id":0},{$set:{"name":"小呆呆"}})
db.users.updateOne({"_id":10},{$set:{"name":"熊大"}},{upsert:true});
db.collection.updateMany():向指定集合更新多个文档
db.users.updateMany({"name":"小崔加油"},{$set:{"name":"欧力给"}});
文档查询
MongoDB 查询文档使用 find() 方法。find() 方法以非结构化的方式来显示所有文档
语法
db.集合名称.find(query, projection)
- query :可选,使用查询操作符指定查询条件
- projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)
如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:
db.集合名称.find().pretty()
注意: pretty()方法以格式化的方式来显示所有文档。
对比语法
如果你熟悉常规的 SQL 数据,通过下表可以更好的理解 MongoDB 的条件语句查询:
- db.users.find({"age":{$gte:15}})
AND
db.集合名称.find({key1:value1, key2:value2,...}).pretty()
类似于 WHERE 语句:WHERE key1=value1 AND key2=value2
- db.users.find({"age":27,"name":"欧力给",_id:8});
- db.users.find({"age":3,"age":27});同一字段多次出现查询条件时,只有最后的查询条件才生效,即后面会覆盖前面的查询条件
OR
MongoDB OR 条件语句使用了关键字 $or,语法格式如下:
db.集合名称.find(
{
$or: [
{key1: value1}, {key2:value2}
]
}
).pretty()
类似于 WHERE 语句:WHERE key1=value1 or key2=value2
- db.users.find({$or:[{_id:3},{age:15}]});
AND 和 OR 联合
类似SQL语句为:'where age >50 AND (name = '编程不良人' OR name = 'MongoDB')'
db.集合名称.find({"age": {$gt:50}, $or: [{"name": "编程不良人"},{"name": "MongoDB"}]}).pretty();
- db.users.find({age:{$gt:15},$or:[{_id:3},{age:15}]});
数组中查询
-- 测试数据
db.集合名称.insert({ "_id" : 11, "age" : 29, "likes" : [ "看电视", "读书xx", "美女" ], "name" : "不良人_xx_11" })
-- 执行数组查询
db.users.find({likes:"看电视"})
-- $size 按照数组长度查询
db.users.find({likes:{$size:3}})
模糊查询
类似 SQL 中为 'where name like '%name%''
db.users.find({likes:/良/});
注意:在 mongoDB 中使用正则表达式可以是实现近似模糊查询功能
排序
db.集合名称.find().sort({name:1,age:1}),
1 升序 -1 降序
类似 SQL 语句为: 'order by name,age'
分页
db.集合名称.find().sort({条件}).skip(start).limit(rows);
类似于 SQL 语句为: 'limit start,rows'
总条数
db.集合名称.count();
> db.集合名称.find({"name":"编程不良人"}).count();
类似于 SQL 语句为: 'select count(id) from ....'
去重
db.集合名称.distinct('字段')
类似于 SQL 语句为: 'select distinct name from ....'
- db.users.distinct("age");
指定返回字段
> db.集合名称.find({条件},{name:1,age:1})
- 参数2: 1 返回 0 不返回
db.users.find({},{"name":1});查询所有,返回指定字段
db.users.find({age:{$lt:17}},{name:1});按照指定条件查询,返回指定字段
db.users.find({age:{$lt:17}},{_id:0,name:1});按照指定条件查询,返回指定字段,不返回id,注意id是唯一索引
$type
说明
$type操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果。
MongoDB 中可以使用的类型如下表所示:
使用
db.col.insert({
title: 'PHP 教程',
description: 'PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。',
by: '不良人1',
url: 'http://www.baizhiedu.xin',
tags: ['php'],
likes: 200
});
db.col.insert({
title: 'Java 教程',
description: 'Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。',
by: '不良人2',
url: 'http://www.baizhiedu.xin',
tags: ['java'],
likes: 550
});
db.col.insert({
title: 'MongoDB 教程',
description: 'MongoDB 是一个 Nosql 数据库',
by: '不良人3',
url: 'http://www.baizhiedu.xin',
tags: ['mongodb'],
likes: 100
});
db.col.insert({
title: 2233,
description: '2233 是一个 B站的',
by: '不良人4',
url: 'http://www.baizhiedu.xin',
tags: ['2233'],
likes: 100
});
- 如果想获取 "col" 集合中 title 为 String 的数据,你可以使用以下命令:
db.col.find({"title" : {$type : 2}}).pretty();
或
db.col.find({"title" : {$type : 'string'}}).pretty()
- 如果想获取 "col" 集合中 tags 为 Array 的数据,你可以使用以下命令:
db.col.find({"tags":{$type : 4}}).pretty();
或
db.col.find({"tags" : {$type : 'array'}}).pretty();
索引<index>
说明
索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构。
原理
从根本上说,MongoDB中的索引与其他数据库系统中的索引类似。MongoDB在集合层面上定义了索引,并支持对MongoDB集合中的任何字段或文档的子字段进行索引。
默认_id已经创建了索引。
操作
0、创建索引
db.集合名称.createIndex(keys, options)
db.集合名称.createIndex({"title":1,"description":-1})
说明: 语法中 Key 值为你要创建的索引字段,1 为指定按升序创建索引,如果你想按降序来创建索引指定为 -1 即可。
createIndex() 接收可选参数,可选参数列表如下:
1、查看集合索引
db.集合名称.getIndexes()
2、查看集合索引大小
db.集合名称.totalIndexSize()
3、删除集合所有索引(不包含_id索引)
db.集合名称.dropIndexes()
4、删除集合指定索引
db.集合名称.dropIndex("索引名称")
复合索引
说明: 一个索引的值是由多个 key 进行维护的索引的称之为复合索引
db.集合名称.createIndex({"title":1,"description":-1})
注意: mongoDB 中复合索引和传统关系型数据库一致都是左前缀匹配原则
聚合<aggregate>
说明
MongoDB 中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。有点类似 SQL 语句中的 count(*)。
使用
db.test.insertMany([
{
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: 'No sql 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.neo4j.com',
tags: ['neo4j', 'database', 'NoSQL'],
likes: 750
}
]);
现在我们通过以上集合计算每个作者所写的文章数,使用aggregate()计算结果如下:
db.集合名称.aggregate([{$group : {
_id : "$by_user",
num_tutorial : {$sum : 1}
}}])
注意:此处的_id是分组表示,不是文档的 _id.
常见聚合表达式
navicat可视化界面
远程连接时需要注意
1.默认解压安装的mongodb时没有开启远程服务的需要设置–bind_id=0.0.0.0开启
2.docker运行的mongodb默认时开启远程服务的v
springboot整合
Spring Data:Spring 数据框架 JPA 、Redis、Elasticsearch、AMQP、MongoDB
1.导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>
spring-boot-starter-data-mongodb
</artifactId>
</dependency>
2.编写配置
# 默认无安全验证
spring.data.mongodb.uri=mongodb://1.14.17.152:27017/chihiro
# 又安全验证时
#spring.data.mongodb.host=1.14.17.152
#spring.data.mongodb.port=27017
#spring.data.mongodb.username=root吧
#spring.data.mongodb.password=***
操作集合
集合创建
boolean db21 = mongoTemplate.collectionExists("db2");
if (db21 == false) {
mongoTemplate.createCollection("db2");
}
集合删除
mongoTemplate.dropCollection("db2");
文档添加
mongoTemplate.insert(new User(4, "小wangb", 22, new Date()), "db1");
mongoTemplate.save(new User(1,"小米",22,new Date()));
mongoTemplate.insert(Arrays.asList(new User(2, "小号", 11, new Date()),new User(3, "chiwan", 99, new Date())), User.class);
--insert 可以批量插入数据,重复id会报错
--save不可以批量插入数据,重复id不会报错
文档查询
//根据id查询
mongoTemplate.findById(1, User.class);
//查询所有
mongoTemplate.findAll(User.class);
//等值查询
mongoTemplate.find(Query.query(Criteria.where("name").is("小红")), User.class);
//<,>,>=,<=
mongoTemplate.find(Query.query(Criteria.where("age").lt(33)), User.class);
//and查询
mongoTemplate.find(Query.query(Criteria.where("name").is("小号").and("age").is(11)), User.class);
//or查询
Criteria criteria = new Criteria();
criteria.orOperator(Criteria.where("name").is("小号"), Criteria.where("name").is("小红"));
mongoTemplate.find(Query.query(criteria), User.class);
//and or 查询
mongoTemplate.find(Query.query(Criteria.where("age").is(22).orOperator(Criteria.where("name").is("小红"), criteria.where("name").is("小wangb"))), User.class);
//排序
mongoTemplate.find(new Query().with(Sort.by(Sort.Order.desc("age"))), User.class);
//分页
mongoTemplate.find(new Query().with(Sort.by(Sort.Order.desc("age"))).skip(3).limit(2), User.class);
//总条数
mongoTemplate.count(new Query(), User.class);
//去重
mongoTemplate.findDistinct(new Query(), "age", User.class, int.class);
//传统采用Json格式查询
mongoTemplate.find(new BasicQuery("{$or:[{age:22},{age:99}]}", "{name:0}"), User.class);
文档更新
//更新第一条
Query query = new Query(Criteria.where("age").is(44));
mongoTemplate.updateFirst(query, new Update().set("age", 33).set("name", "小王八"), User.class);
//更新批量
mongoTemplate.updateMulti(query, new Update().set("age", 11), User.class);
//更新插入
UpdateResult age = mongoTemplate. (query, new Update().set("age", 44), User.class);
System.out.println(age.getModifiedCount());//修改条数
System.out.println(age.getMatchedCount());//匹配条数
System.out.println(age.getUpsertedId());//插入id
文档删除
//条件删除
mongoTemplate.remove(new Query(Criteria.where("age").is(44)), User.class);
//删除所有
mongoTemplate.remove(new Query(), User.class);