1.认识MongoDB [MongoDB](MongoDB: the application data platform | MongoDB ) 是一个非关系型数据
数据模型比较简单(主要)
需要灵活性更强的应用系统
对数据库性能要求较高(主要)
不需要高度的数据一致性(主要)
对于给定key,比较容易映射复杂值的环境.
应用场景
游戏场景 ,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新
视频直播 ,使用 MongoDB 存储用户信息、礼物信息等
日志处理
物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。
社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能
物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析
MongoDB半内存数据库, 可能会有60s间隔数据数据丢失(可通过集群方式解决 )
MongoDB优势
以自然的方式来建模, 以直观的方式来与数据库交互
采用bson结构存储数据
可以简单理解升级版json格式
结构灵活 : 弹性模式从容响应需求的变更
快速开发 : 做更多的事,写更少的代码
原生的高可用与易扩展
单机模式:开始与测试
复制集模式:数据量不大应用, 需要事务支持的应用
分片集群模式:大数据量应用
2.MongoDB核心概念 基本概念
数据库:
MongoDB 的一个实例可以拥有一个或者多个相互独立的数据库, 每个数据库都有自己的集合 命令: show databases;
集合:
集合可以看做是拥有动态模式的表, json格式, 可以更加业务需求自动拓展, 一个集合可以用于n个文档 命令: use 数据库; show collections;
文档:
文档是MongoDB 中基本的数据单元, 类似于mysql的行 文档是键值对的一个有序集合。在js语法中就是 { }
_id:
每个文档都会有个特殊的_id, 是文档所属集合中的唯一
MongoDB与Mysql对比
1:都是数据库概念 2:集合 – 表 3:文档 — 一条记录(行) 4:文档中的key — 表字段 5:文档中的value —- 字段值 6:MongoDB没有主外键的概念
语法规则
数据库名定义规则
1:不能是空串 2:不能含有 / \ ? $ 空格 空字符串 3:区分大小写,建议全部小写 4:最多为64个字节 5:不能使用保留名字: admin local config
PS: 数据库最终成为文件, 数据库名就是文件名
集合名称定义规则
1:不能是空串 2:不能含有 / \ ? $ 空格 空字符串 3:不能以 system. 开头, 这些都是系统保留集合前缀
文档定义规则
1:不能是空串 2:不能含有 / \ ? $ 空格 空字符串 3: . $ 保留字符 4:区分类型, 同时区分大小写 5:键不能重复
数据类型
数据类型
描述
举例
null
表示空值或者未定义的对象
{“x”: null}
boolean
true/false
{“x”: true/false}
int
32位整数
{“x”: NumberInt(“3”)}
long
64位i整数
{“x”: NumberLong(“3”)}
double
浮点数
{“x”:3.14, “y”:3}
string
UTF-8字符串
{“x”:”dafei”}
_id
12字节的唯一id,自动生成
{“_id”:ObjectId(“5e2ab4f48847000059006f73”)}
date
从标准纪元开始的毫秒数
{“date”:ISODate(“2018-11-26T00:00:00.000Z”)}
Regular expression
正则表达式,语法同js的正则对象
{“x”: /foobar/i}
code
JavaScript代码块
{“x”:function(){….}}
undefined
未定义
{“x”:undefined}
array
值集合或者列表
{“x”:[“a”,”b”]}
object
文档中嵌入另外一个文档
{“x”:{“a”:1, “b”:2}}
3.MongoDB操作 官方操作文档
文档添加 1 2 3 4 5 6 7 8 9 语法: db.集合名.insert( 文档 ) : 往集合中插入一个文档或者多个 注意: 1 :往集合中新增文档,当集合不存在时会自动先创建集合2 :当操作成功时,集合会给文档生成一个_id字段,也可以自己指定db.users.insert({id : 1 , name : "xiaowen" , age : 21 }) db.users.insert({id : 2 , name : "xiaoyuan" , age : 18 })
文档更新 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 格式: db.集合名.updateOne( <query>, <update> ) db.集合名.updateMany( <query>, <update> ) query : update的查询条件,类似sql update查询内where后面的。update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的db.users.updateOne({name : "xiaowen" }, {$set : {age : 30 }}) db.users.updateMany({name : "xiaowen" }, {$set : {name : "小文" , age : 21 }}) db.users.updateMany({}, {$set : {name : "xxx" , age : 10 }})
文档删除 1 2 3 4 5 6 7 8 9 10 11 12 13 删除1 个: db.集合名.deleteOne(<query>) 删除多个: db.集合名.deleteMany(<query>) db.users.deleteOne({_id : ObjectId("xxx" )}) db.users.deleteMany({name : "xiaowen" }) db.users.deleteMany({})
查询全部 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 33 34 35 36 --------------------查询---------------------- 语法: db.集合名.find(query, projection) query :是条件projection :列的投影,指定返回哪些列 _id默认返回 eg: {"_id" : 0 }查所有用户 db.users.find() db.users.find({}) db.users.find({}, {name :1 }) --------------------排序---------------------- sort({列: 1 }) sort({列:-1 }) 多列排序 sort({列1 :1 , 列2 :1 }) 查询所有用户按年龄排序 db.users.find({}).sort({age :1 }) db.users.find({}).sort({age :-1 }) db.users.find({}).sort({age :-1 , id :1 }) --------------------分页---------------------- db.集合.find({}).skip(n).limit(m) 分页查询所有用户 db.users.find().skip(0 ).limit(3 ) db.users.find().skip(3 ).limit(3 ) db.users.find().skip((currentPage-1 ) * pageSize).limit(pageSize)
条件查询 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 语法: db.集合名. find({字段: {比较操作符: 值, ...}}) >(大于 ) => $gt <(小于 ) => $lt >=(大于等于 ) => $gte <=(小于等于 ) => $lte !=(不等 ) => $ne is null {$exists : false } in {$in : [xx, xx ...]}查询age > 18 的用户 db.users.find( {age : { $gt :30 }} ) 查询名字为 xiaowen 或 xiaoyuan 用户 db.users.find( {name : {$in : ["xiaowen" , "xiaoyuan" ]}} ) 判断判断指定列是否存在 db.users.find( {name : {$exists :true }} )
逻辑运算符 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 语法: find({逻辑操作符: [条件1 , 条件2 , ...]}) && 与 => $and || 或 => $or ! 非 => $not 查年龄在28 到 30 间的用户信息 db.users.find( {age :{$gte :28 , $lte :30 }} ) db.users.find( { $and :[{age :{$gte :28 }},{age :{$lte :30 }}] } ) 查看年龄小于28 或者年龄大于30 用户信息 db.users.find( {$or : [{age : {$lt : 28 }}, {age : {$gt :30 }}]} ) 查看年龄等于28 或者等于30 用户信息 db.users.find( {$or : [{age :28 }, {age : 30 }]} )
模糊查询 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 db.集合.find({列: {$regex : /关键字/ }}) db.集合.find({列: {$regex : "关键字" }}) {name :/xxx/ } => %xxx% {name :/^xxx/ } => xxx% {name :/xxx$/ } => %xxx {name :/xxx/i } 查询name带有fei的用户信息 db.users.find( {name : {$regex :/xiao/ }} ) 查name中包含xiao字样,并且年龄在28 到30 间的用户信息, db.users.find( {$and : [{name : {$regex :/xiao/ }}, {age : {$gte :28 , $lte :30 }}]} )
4.集成springboot 依赖
1 2 3 4 5 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-data-mongodb</artifactId > </dependency >
配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 spring: data: mongodb: uri: mongodb://localhost/mongo-demo logging: level: org: springframework: data: mongodb: core: debug
domain
1 2 3 4 5 6 7 8 9 10 11 12 @Setter @Getter @Document("users") public class User { @Id private String id; private String name; private Integer age; private List<String> hobby = new ArrayList<>(); }
repository
1 2 3 4 5 @Repository public interface UserRepository extends MongoRepository <User , String > { List<User> findByName (String name) ; }
service
1 2 3 4 5 6 7 8 9 10 11 12 13 public interface IUserService { void save (User user) ; void delete (String id) ; void update (User user) ; User get (String id) ; List<User> list () ; }
service.impl
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 @Service public class UserServiceImpl implements IUserService { @Resource private UserRepository userRepository; @Override public void save (User user) { userRepository.save(user); } @Override public void delete (String id) { userRepository.deleteById(id); } @Override public void update (User user) { userRepository.save(user); } @Override public User get (String id) { return userRepository.findById(id).get(); } @Override public List<User> list () { return userRepository.findAll(); } }
JPA规范
分页查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Autowired private MongoTemplate mongoTemplate;@Test public void testQuery1 () throws Exception { Query query = new Query(); query.skip(3 ).limit(3 ); query.with(Sort.by(Sort.Direction.ASC,"id" )); List<User> list = mongoTemplate.find(query, User.class, "users" ); list.forEach(System.err::println); }
条件查询
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 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 68 69 @SpringBootTest public class QueryTest { @Autowired private MongoTemplate mongoTemplate; @Test public void testQuery1 () throws Exception { Query query = new Query(); query.skip(3 ).limit(3 ); query.with(Sort.by(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("xiao" ); 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("xiao" ), 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(".*xiao.*" ), 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); } }