前言:本文为原创 若有错误欢迎评论!
一.基本介绍
1.安装
请参考后面博客的centos安装应用的博客:https://blog.csdn.net/weixin_43934607/article/details/100538881
2.使用场景
- Mongodb性能好 但有丢失数据的可能(不是缓存 是持久化到磁盘)
- 数据量大
- 写入操作频繁
- 价值较低
3.与SQL中的概念进行对比
二.数据类型
1.null:
用于表示空值或者不存在的字段,{“x”:null}
2.布尔型:
布尔类型有两个值true和false,{“x”:true}
3.数值:
shell默认使用64为浮点型数值。{“x”:3.14}或{“x”:3}。对于整型值,可以使用
4.NumberInt(4字节符号整数)或NumberLong(8字节符号整数)
{“x”:NumberInt(“3”) } 或 {“x”:NumberLong(“3”) }
5.字符串:
UTF-8字符串都可以表示为字符串类型的数据,{“x”:“呵呵”}
6.日期:
日期被存储为时间戳(自新纪元依赖经过的毫秒数,不存储时区) {“x”:new Date()}
7.正则表达式:
查询时,使用正则表达式作为限定条件,语法与JavaScript的正则表达式相同,{“x”: /[abc]/ }
8.数组:
数据列表或数据集可以表示为数组,{“x”: [“a“,“b”,”c”]}
9.内嵌文档:
文档可以嵌套其他文档(即bson嵌套bson),被嵌套的文档作为值来处理,{“x”:{“y”:3 }}
10.对象Id(ObjectId类型):
对象id是一个12字节的字符串,是文档的唯一标识,{“x”: objectId() }
11.二进制数据:
二进制数据是一个任意字节的字符串。它不能直接在shell中使用。如果要将非utf-字符保存到数据库中,二进制数据是唯一的方式。
11.代码:
查询和文档中可以包括任何JavaScript代码,{“x”:function(){/…/}}
三.常用命令
数据库及表的操作
-
use 数据库名称
使用某个数据库 如果没有会自动创建 并且自动切换到该数据库use spitdb
-
show dbs
显示所有数据库 -
show tables
显示所有的表 -
db.表名.drop()
删除表db.spitdb.drop()
-
db.dropDatabase()
删除数据库 (但必须进入要删除的数据库才可以执行)
新增数据
-
db.集合名称.insert()
给数据库插入文档 如果不存在该集合就自动创建db.表名.insert( { content:“内容” , userid:“1011” , nickname:“小雅” , visits:NumberInt(902) } )
- 注意:
- 字段的名字不用带" "
- 每条文档会有一个"_id"的字段,相当于关系数据库中表的主键,若在插入文档记录时没有指定该字段,MongoDB会自动创建,其类型是ObjectID类型。如果在插入文档记录时指定该字段 其可以是MongoDB支持的任意类型。
- 注意:
更新数据
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 :可选,抛出异常的级别。
-
db.集合名称.update(条件,修改后的数据)
更新集合中的数据(没被更新的字段会被删除)db.表名.update({_id:“1”},{visits:NumberInt(1000)})
注意:()里写的是两个bson数据 -
db.集合名称.update( { 条件 } , {$set : 修改后的数据 } )
更新集合中的数据(没被更新的字段值不变)db.表名.update({_id:“2”},{$set:{visits:NumberInt(2000)}})
删除数据
db.collection.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)
参数说明:
query :(可选)删除的文档的条件。
justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删
除所有匹配条件的文档。
writeConcern :(可选)抛出异常的级别。
-
db.集合名称.remove(条件)
删除文档db.表名.remove({}) #删除全部数据
db.表名.remove({visits:1000})
查询数据
db.collection.find([query],[fields])
参数说明:
query :可选,使用查询操作符指定查询条件
fields :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省
略)。
-
db.集合名称.find()
查询集合中的数据db.表名.find({userid:‘1013’})
注意:find里面只能写一个查询条件 -
db.集合名称.findOne()
和find()的区别是只返回查询到的第一条数据db.表名.findOne({userid:‘1013’})
-
db.集合名称.find().limit()
限制查询的条数db.表名.find().limit(3)
-
db.表名.count()
统计条数db.表名.count({userid:“1013”})
-
db.表名.find({ filed : /模糊查询字符串/})
模糊查询–只要包含该字符串即可db.表名.find({content:/流量/})
-
db.表名.find({ filed : /^ 模糊查询字符串/})
模糊查询–必须以该字符串开头db.表名.find({content:/^加班/})
注意:模糊查询的字符串不需要带" ". -
db.表名.find().pretty()
pretty() 方法以格式化的方式来显示所有文档 -
db.集合名称.find({ field : { $gt: value }})
大于: field > value -
db.集合名称.find({ field : { $lt: value }})
小于: field < value -
db.集合名称.find({ field : { $gte: value }})
大于等于: field >= value -
db.集合名称.find({ field : { $lte: value }})
小于等于: field <= value -
db.集合名称.find({ field : { $ne: value }})
不等于: field != valuedb.表名.find({visits:{$gt:1000}})
-
db.集合名称.find ({ field : { $in: [value1,value2,value3]} })
包含db.表名.find({userid:{$in:[“1013”,“1014”]}})
-
db.集合名称.find ({ field : { $nin: [value1,value2,value3]} })
不包含db.表名.find({userid:{$nin:[“1013”,“1014”]}})
-
db.集合名称.find( {$and : [ { : },{ : },{ : } ] })
条件连接–和db.表名.find({KaTeX parse error: Expected '}', got 'EOF' at end of input: and:[ {visits:{gte:1000}} ,{visits:{$lt:2000} }]})
-
db.集合名称.find( {$or : [ { : },{ : },{ : } ] })
条件连接–或者db.表名.find({KaTeX parse error: Expected '}', got 'EOF' at end of input: …13"} ,{visits:{lt:2000} }]})
-
db.表名.update({ { : },{$inc : { : } } )
指定文档 让其某个字段值增加db.表名.update({_id:“2”},{$inc:{visits:NumberInt(1)}} )
索引
- db.表名.getIndexes()
查看索引
#执行结果:
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "数据库名.表名"
}
]
##说明:1表示升序创建索引,-1表示降序创建索引。
- db.表名.createIndex({‘索引字段名’:1})
创建索引
#执行结果:
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
-
db.表名.dropIndex(“id”)
删除索引 (age_1是查看索引时对应的name那项) -
db.表名.dropIndexes()
或者,删除除了_id之外的索引 -
db.表名.createIndex({‘索引名1’:1, ‘索引名2’:-1})
创建联合索引 -
db.表名.totalIndexSize()
查看索引大小,单位:字节
执行计划
- db.表名.find(查询条件).explain()
查看执行计划
关注winningPlan的stage项,stage对应执行计划
"winningPlan" : {
#执行计划
"stage" : "FETCH",
...
}
- 查询方式
- COLLSCAN/全表扫描
- IXSCAN/索引扫描
- FETCH/根据索引去检索文档
- SHARD_MERGE/合并分片结果
- IDHACK/针对_id进行查询
四.SpringBoot整合Mongodb
1.依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐data‐mongodb</artifactId>
</dependency>
2.配置文件
spring:
application:
name: #指定服务名
data:
mongodb:
host: 192.168.56.129
database: #指定数据库的名字
3.创建要存储的集合
@Document(collection = "user")
public class User {
@Id
private ObjectId id;
@Field("username")
@Indexed
private String userName;
private String password;
@Transient
private boolean isOnline;
}
- 注意:
- @Document:如果不说明使用的集合 默认会使用类名作为集合名
- @Id:如果不声明主键 mongodb默认时_id 并且是ObjectId类型的主键(org.springframework.data.annotation.Id)
- @Field(“username”):数据库字段名和类中不同时,驼峰式会自动转化成下划线
- @Indexed:该字段作为索引
- @Transient:加入数据库时忽略该字段
使用方式一:extends MongoRepository(简单查询推荐)
1.创建数据访问接口 extends MongoRepository<集合的类型 , 索引的类型>
public interface UserRepository extends MongoRepository<User, String>{
}
2.使用
-
直接注入上一步的接口
@Autowired private UserRepository userRepository;
-
直接继承的MongoRepository的方法
- findAll()
- findById()
- save() //更新也是用这个 如果存在就跟新 不存在就创建
- delete()
- deleteAll()
- deleteById()
- existById()
-
特定条件查询 (比如指定字段或者分页)
在Dao的接口中添加新的查询方法 springdata会自动根据方法生成查询语句 就在正常写方法的"返回类型、字段名"时 就会有提示 然后把参数补上就可以public interface UserRepository extends MongoRepository<User, String>{ public Page<Test> findByName(String name,Pageable pageable); }
使用方式二:注入MongoTemplate(复杂查询语句推荐)
-
注入MongoTemplate
@Autowired private MongoTemplate mongoTemplate;
-
查询
//构建查询条件 Criteria criteria_1 = Criteria.where("字段名").is(值); Criteria criteria_2 = Criteria.where("字段名").gt(值).and("字段名").lt(值); //如果有多个查询条件:组合查询条件 Criteria criteria=new Criteria().orOperator(criteria_1 ,criteria_2 ); //构建分页查询和排序(可以不构建) PageRequest pagerequest = PageRequest.of(page, rows, Sort.by(Sort.Direction.ASC,"字段名")); //组合成Query Query query=new Query(criteria).with(pagerequest); //执行查询 mongoTemplate.find(query, 类.class)
-
增加
mongoTemplate.save(对象)
-
修改
//构建Query Query query = Query.query(Criteria.where("id").is(id)); //构建要修改的字段 Update update = new Update(); update.set("字段名1", 值); update.set("字段名2", 值); //执行更新 mongoTemplate.updateFirst(query, update, 类.class)
-
删除
//构建Query Query query = Query.query(Criteria.where("id").is(id)); //执行删除 mongoTemplate.remove(query, 类.class);
关于Springdata的分页查询
1.Page<>
Page是Springdata提供的分页查询的返回结果
- 常用的三个方法:
- int getTotalPages() 总的页数
- long getTotalElements() 返回总数
- List getContent() 返回此次查询的结果集
2.Sort:Springdata提供的为查询结果排序的
Sort sort = new Sort(“id”); // 或 Sort sort = new Sort(Direction.ASC,“id”);
3.PageRequest:Pageable的子类PageRequest来存储分页的条件(其中page从0开始)
PageRequest pageRequest = PageRequest.of(page-1, size,Sort.by(Sort.Direction.ASC,“字段名”));