Mongodb学习
创建数据库-集合(表)
-
使用指定数据库(没有会创建):
use DATABASE_NAME
, 如果数据库不存在,则创建数据库,否则切换到指定数据库。- 如:
use douban
, 此时db就变成了douban,之后db.xxxx()
都默认在这个数据库下操作
- 如:
-
查看所有数据库,可以使用
show dbs
-
创建集合:
db.createCollection(name, options)
-
随意创建集合,
db.createCollection("top250");
-
options 可以是如下参数:
字段 类型 描述 capped 布尔 (可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。 当该值为 true 时,必须指定 size 参数。 autoIndexId 布尔 3.2 之后不再支持该参数。(可选)如为 true,自动在 _id 字段创建索引。默认为 false。 size 数值 (可选)为固定集合指定一个最大值,即字节数。 如果 capped 为 true,也需要指定该字段。 max 数值 (可选)指定固定集合中包含文档的最大数量。 -
创建固定集合:
db.createCollection("mycol", { capped : true, autoIndexId : true, size : 6142800, max : 10000 } )
-
-
查看已有集合,可以使用 show collections 或 show tables 命令:
插入文档
db.COLLECTION_NAME.insert(document)
或db.COLLECTION_NAME.save(document)
- save():如果 _id 主键存在则更新数据,如果不存在就插入数据。该方法新版本中已废弃,可以使用 db.collection.insertOne() 或 db.collection.replaceOne() 来代替。
- insert(): 若插入的数据主键已经存在,则会抛 org.springframework.dao.DuplicateKeyException 异常,提示主键重复,不保存当前数据。
- 3.2 版本之后新增了 db.collection.insertOne() 和 db.collection.insertMany()。
查询find:
在MongoDB中可以使用find0函数查询文档。
语法格式为:find(){查询条件(可选)},{指定投影的键(可选)})
如果未给定参数则表示查询所有数据。 当查询所有,要制定投影键的时候得列出前面的大括号,如find({键: {操作符: 条件}}, {投影键名: 1(显示该列)| 0(不显示该列), ..})
, 如果不想显示_id
可以这么写: find({},{_id: 0})
prettyO函数可以使用格式化的方式来显示所有文档。
$and
和$or
联合使用
查询title为test5并且size等于500,或者size小于400的文档。
db.dev.find({$or:[{$and:[{title:{$eq:"test5"}},{size:500}]},{size:{$Lt:409}}]})
聚合查询aggregate
SQL操作函数 | mongodb聚合操作 |
---|---|
where | $match 在$groupby 前侧 |
group | $group |
having | $match 在$groupby 后侧 |
select | $project |
order by | $sort |
limit | $limit |
join | $lookup |
1 | // aggregate中一定是个数组格式 |
例子: 求和
查询dev集合中一共有多少个文档。
相当于sql语句:SELECT count(*)AS count FROM dev
db.dev.aggregate([{$group:{_id:null.count:($sum:1}}}])
- $group:分组,代表聚合的分组条件
- _id:分组的字段。相当于SQL分组语法group by column name中的column name部分。
如果根据某字段的值分组,则定义为id:’$字段名’。所以此案例中的null代表一个固定的字面值null,表示对所有列即整表。 - count:返回结果字段名。可以自定义,类似SQL中的字段别名。
- $sum:求和表达式。相当于SQL中的sumO。
- 1:累加值。如果是对某列如size求值和,则1改为""$size"
管道
MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。
管道操作符是按照书写的顺序依次执行的,每个操作符都会接受一连串的文档,对这些文档做一些类型转换,最后将转换后的文档作为结果传递给下一个操作符(对于最后一个管道操作符,是将结果返回给客户端),称为流式工作方式。
管道操作符:$match
、$group
、$sort
、$limit
、$skip
、$unwind
, 管道操作符,只能用于计算当前聚合管道的文档,不能处理其它的文档。
MongoDB 的 aggregate 是可以分为多个阶段的(pipeline)
-
第一阶段,$match,这里可以参考《MongoDB:查询和投影操作符》这篇文章,根据条件去查找。
-
第二阶段,$project,表示要哪个域,不要哪个域,或者投影成别的一个域,这里表示 value 域保留,status 域,根据条件来转换成 “confirmed” 或者 “unconfirmed”,_id 不要。
-
第三阶段,status来表示,balance 是对之前的$value进行求和。
常用命令:
-
$project
:使用$project
操作符做聚合投影操作从而修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。如db.dev.aggregate([{Sunwind:"Stags"},{Sproject:{id:0,Tags:"$tags",Title:"$title"}}])
从而不显示id, 并且可以取别名 -
$match
:用于过滤数据,只输出符合条件的文档。$match
使用MongoDB的标准查询操作。 -
$limit:用来限制MongoDB聚合管道返回的文档数。
-
$skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
-
// Aggregation.lookup("student", "student_id", "_id", "student") 参数含义如下 LookupOperation lookupOperation=LookupOperation.newLookup(). from("grade"). //关联从表名 localField("gradeId"). //主表关联字段 foreignField("_id").//从表关联的字段 as("GradeAndStu"); //查询结果名
-
unwind:将文档中的某一个**数组类型字段拆分成多条**,每条包含数组中的一个值。如查询dev集合,将其中数组内的内容拆分显示(会生成多个id相同的查询结果),`db.dev.aggregate([{unwind:"$tags"}])`
-
$group:将集合中的文档分组,可用于统计结果。
操作内嵌文档
操作数组
对数组根据条件查询
$all、$size、$slice、$elemMatch
- $all查找数组中包含指定的值的文档
- $size 查找数组大小等于指定值的文档
- slice·可以查询数组中第几个到第几个
对数组内嵌文档查询
$elemMatch
文档包含有一个元素是数组,那么$elemMatch
可以匹配内数组内的元素并返回文档数据db.orders.find({"items":{$elemMatch:{"quantity":2}}})
- elemMatch可以带多个查询条件`db.orders.find({"items":{elemMatch:{“quantity”:4,“ino”:“002”}}}) `
$elemMatch
同样可以用在find方法的第二个参数来限制返回数组内的元素,只返回我们需要的文档db.orders.find({"onumber":"001"},{"items":{$elemMatch:{"quantity":4,"ino":"002"}},"cname":1,"date":1,"onumber":1})
from;
- MongoDB查询(数组、内嵌文档)(二)
- MongoDB 几种查询嵌套数据(Embedded)的方式——
$
映射操作符(Projection Operator)、$elemMatch
映射操作符(Projection Operator) - MongoDB高级查询详细
完整demo:
1 | public JobPositionDetailsVO getJobPositionDetails(String orgId, String jpId) { |
使用MongoRepository完成CURD和复杂查询
与HibernateRepository类似,通过继承MongoRepository接口,我们可以非常方便地实现对一个对象的增删改查,要使用Repository的功能,先继承MongoRepository<T, TD>
接口,其中T为仓库保存的bean类,TD为该bean的唯一标识的类型,一般为ObjectId。之后在service中注入该接口就可以使用,无需实现里面的方法,spring会根据定义的规则自动生成。
1 | public interface PersonRepository extends |
但是MongoRepository实现了的只是最基本的增删改查的功能,要想增加额外的查询方法,可以按照以下规则定义接口的方法。自定义查询方法,格式为findBy+字段名+方法后缀
,方法传进的参数即字段的值,此外还支持分页查询,通过传进一个Pageable对象,返回Page集合。
1 | public interface PersonRepository extends |
from : MongoRepository基本方法
尽管以上查询功能已经很丰富,但如果还不能满足使用情况的话可以用一下方法——基于mongodb shell查询语句的查询方式,即在DAO接口中加入
1 | "{ 'name':{'$regex':?2,'$options':'i'}, sales': {'$gte':?1,'$lte':?2}}") ( |
注解Query里面的就是mongodb原来的查询语法,我们可以定义传进来的查询参数,通过坐标定义方法的参数。
还可以在后面指定要返回的数据字段,如上面的例子修改如下,则只通过person表里面的name和age字段构建person对象。
1 | "{ 'name':{'$regex':?2,'$options':'i'}, sales':{'$gte':?1,'$lte':?2}}",fields="{ 'name' : 1, 'age' : 1}") (value= |
对比mongotemplate和mongoRepository
1MongoTemplate
MongoTemplate 遵循Spring中的标准模板模式,并为底层持久性引擎提供准备就绪的基本API。
1 | // 1. 校验添加的物资类型是否存在 |
1 | val criteria = Criteria().andOperator( |
2MongoRepository
以Spring Date为中心的方法,基于所有Spring数据项目中众所周知的访问模式,提供更加灵活和复杂的api操作。
Spring boot集成mongodb使用MongoRepository完成CURD和复杂查询
-
findByOrderByDictTypeCodeDescAndSortNumDesc失败
-
findAllByOrderByIdDesc和findByOrderByIdDesc 效果一样
-
dictionaryInfoDao.findAllByOrderByIdDesc(Sort.by(Sort.Direction.DESC,"sortNum"));
后面的排序无效 -
1
2
3
4
5findAllByOrderByIdDescAndOrderBySortNumDesc
findAllByOrderByIdDescAndSortNumDesc(Sort sort)
dictionaryInfoDao.findAll(Sort.by("dictTypeCode"), Sort.by("sortNum"));
失效
MyBatis与JPA的区别是什么
JPA是JAVA持久层API的规范, JPA仅仅定义了一些接口,而接口是需要实现才能工作的。 所以底层需要某种实现,而Hibernate就是实现了JPA接口的ORM框架。
Mybatis优势
- MyBatis可以进行更为细致的SQL优化,可以减少查询字段。
- MyBatis容易掌握,而Hibernate门槛较高。
Hibernate优势
-
Hibernate的DAO层开发比MyBatis简单,Mybatis需要维护SQL和结果映射。
-
Hibernate对对象的维护和缓存要比MyBatis好,对增删改查的对象的维护要方便。
-
Hibernate数据库移植性很好,MyBatis的数据库移植性不好,不同的数据库需要写不同SQL。
-
Hibernate有更好的二级缓存机制,可以使用第三方缓存。MyBatis本身提供的缓存机制不佳
-
fun findAllByDictTypeCode(dictTypeCode: String): List<DictionaryInfo>
返回的是个List, 如果没有值则为空列表 -
如果findById的结果是个Optional, 如果自定义
findByXxxx
方法时,返回值可以定义为Optional<XxxxDO>
也可以直接定义成XxxxDO?
Author: Mrli
Link: https://nymrli.top/2021/12/02/Mongodb学习/
Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.