MongoRepository查询数据常用语法
安装
查看mongo可用版本
docker search mongo
安装指定版本的mogo或者拉取最新版本的镜像
docker pull mongo:latest
或者官网下载安装包
https://www.mongodb.com/try/download/community-kubernetes-operator
下载完成解压至自己的目录
tar -zxvf mongodb-macos-x86_64-4.2.18.tgz
创建mongo数据持久化目录
sudo mkdir -p /usr/local/var/mongodb
创建mongo数据库日志目录
sudo mkdir -p /usr/local/var/log/mongodb
分配权限
sudo chown my_mongodb_user /usr/local/var/mongodb
sudo chown my_mongodb_user /usr/local/var/log/mongodb
运行mongod服务
mongod --dbpath /usr/local/var/mongodb --logpath /usr/local/var/log/mongodb/mongo.log --fork
查看是否启动成功
ps aux | grep -v grep | grep mongod
shell操作mongo
mongo
初次安装,只有几个默认的数据库
这里使用spring-boot2.9.4版本.mongo4.2.18
springboot程序查询mongo可以借助MongoRepository或者MongoTemplate,
这里的MongoRepository跟spring data jpa很像,由于继承了CrudRepository或者ListCrudRepository和QueryByExampleExecutor所以基本的增删改查操作都可以直接调用方法来实现
如果使用MongoRepository多字段条件查询时可能会很复杂,使用MongoTemplate查询更为方便,这两者的使用得依靠自己来区分哪种方式更为方便
比如一般的分页以及排序查询MongoRepository更为方便一些
而mongoTemplate只能靠mongoTemplate.query()来实现分页的查询
基础查询
解析查询的方法名称分为主语和谓语find…By,exists…By),第二部分形成谓词,可以进一步操作如,find(或其他引入关键字)和By之间的任何文本可认为形容词,除非使用结果限制关键字,如Distinct在要创建的查询上设置不同的标志,如根据用户名去重复(findDistinctByUsername)或者使用Top/First来限制查询结果(findFirstByUsername),排序之后取前3条数据(findTop3ByOrderByCreateTimeDesc),多个属性表达式也可以用运算符进行连接AND或者OR,如果比较大小也可以用Between、LessThan、GreaterThan来查询,模糊查询Like
interface PersonRepository extends Repository<Person, Long> {
// 多字段and查询
List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);
// 多字段or查询
List<Person> findByEmailAddressOrPhone(EmailAddress emailAddress, String phone);
// 根据username模糊查询
List<UserInfo> findByUsernameLike(String username);
// 根据lastname或者firstname查询,people属性去重
List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);
List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname);
// 忽略大小写
List<Person> findByLastnameIgnoreCase(String lastname);
// 所有属性忽略大小写
List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname);
// 根据firsetname排序
List<Person> findByLastnameOrderByFirstnameAsc(String lastname);
List<Person> findByLastnameOrderByFirstnameDesc(String lastname);
// 时间范围查询 $lt
BookInfo findTopByCreateTimeLessThan(LocalDateTime localDateTime);
// 条数查询
long countByAuthor(String authorName);
}
如果是多条件查询不想使用jpa一直and,又不想使用mongoTemplate的criteria一直添加条件,可以使用注解org.springframework.data.mongodb.repository.@Query注解进行查询
/**
* 自定义查询
* @param showName
* @return
*/
@Query("{showName: ?0}")
List<BookInfo> customQuery(String showName);
Repository中的特殊参数
除了基本类型参数,还可以支持Pageable和 Sort来进行分页和排序
Page<User> findByLastname(String lastname, Pageable pageable);
Slice<User> findByLastname(String lastname, Pageable pageable);
List<User> findByLastname(String lastname, Sort sort);
List<User> findByLastname(String lastname, Pageable pageable);
分页查询
使用Pageable参数来进行分页,使用sort来排序,因为page分页需要根据总数来进行分页计算,判断总共多少页,是否有下一页等等,如果只想分页,不需要知道总共多少页,可使用slice实现,根据属性hasNext判断是否有下一次分页即可,因为计算总页数需要总条数,使用page来接受会额外花费一次count查询
如果只需要排序,可以在方法参数添加sort,可以使用page也可以使用list接受
在jpa查询中,如果添加了pageable,但是不想分页查询,最好使用Pageable.unpaged(),如果不想使用排序可以使用Sort.unsorted()
排序
定义排序表达式,可以多个条件同时排序
Sort sort = Sort.by("firstname").ascending().and(Sort.by("lastname").descending());
lambda条件表达式
TypedSort<Person> person = Sort.sort(Person.class);
Sort sort = person.by(Person::getFirstname).ascending().and(person.by(Person::getLastname).descending());
条数限制
查询的结果集除了使用分页属性控制返回条数之外我们也可以手动限制指定条数,在find...By中间可以使用其他限制词,比如first或者top关键词来限制查询结果的条数,如果只写first或者top,默认为1条,即findByFirst1 = findByFirst = findByTop
User findFirstByOrderByLastnameAsc();
User findTopByOrderByAgeDesc();
Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);
Slice<User> findTop3ByLastname(String lastname, Pageable pageable);
List<User> findFirst10ByLastname(String lastname, Sort sort);
List<User> findTop10ByLastname(String lastname, Pageable pageable);
如果是单条查询,如findFirstByOrderByLastnameAsc可以将返回结果使用实体类接受也可以使用Optional来包装
Optional<User> findFirstByOrderByLastnameAsc();
常用关键词
关键词 | 描述 |
---|---|
find…By,read…By,get…By,query…By,search…By,stream…By | 一般查询方法通常返回存储库类型 |
exists…By | 是否存在,返回boolean或Boolean| |
count…By | 统计条数| |
delete…By,remove…By | 删除方法,无返回结果(void) |
…First |
将查询结果限制为结果的第一个 |
…Distinct… | 使用不同的查询仅返回唯一的结果介于find(和其他关键字)和by。 |
谓词关键词
逻辑关键字 | jpa关键词 |
---|---|
AND | And |
OR | Or |
AFTER | After,IsAfter |
BEFORE | Before,IsBefore |
CONTAINING | Containing,IsContaining,Contains |
BETWEEN | Between,IsBetween |
ENDING_WITH | EndingWith,IsEndingWith,EndsWith |
EXISTS | Exists |
FALSE | False,IsFalse |
GREATER_THAN | GreaterThan,IsGreaterThan |
GREATER_THAN_EQUALS | GreaterThanEqual,IsGreaterThanEqual |
IN | In,IsIn |
IS | Is,Equals |
IS_EMPTY | IsEmpty,Empty |
IS_NOT_EMPTY | IsNotEmpty,NotEmpty |
IS_NOT_NULL | NotNull,IsNotNull |
IS_NULL | Null,IsNull |
LESS_THAN | LessThan,IsLessThan |
LESS_THAN_EQUAL | LessThanEqual,IsLessThanEqual |
LIKE | Like,IsLike |
NEAR | Near,IsNear |
NOT | Not,IsNot |
NOT_IN | NotIn,IsNotIn |
NOT_LIKE | NotLike,IsNotLike |
REGEX | Regex,MatchesRegex,Matches |
STARTING_WITH | StartingWith,IsStartingWith,StartsWith |
TRUE | True,IsTrue |
WITHIN | Within,IsWithin |
谓词修饰符关键词
关键词 | 描述 |
---|---|
gnoreCase,IgnoringCase | 与谓词关键字一起使用,用于不区分大小写的比较 |
AllIgnoreCase,AllIgnoringCase | 忽略所有合适属性的案例。在查询方法谓词的某个地方使用 |
OrderBy… | 指定静态排序顺序,然后是属性路径和方向(例如OrderByFirstnameAscLastnameDesc)。 |
常用返回类型
返回类型 | 描述 |
---|---|
void | 没有返回值 |
T | 一个独特的实体。期望查询方法最多返回一个结果。如果没有找到结果,则返回null。多个结果触发IncorrectResultSizeDataAccessException。 |
Iterator |
|
Collection |
|
List |
|
Optional |
Java 8或GuavaOptional。期望查询方法最多返回一个结果。如果没有找到结果,则返回Optional.empty()或Optional.absent()。多个结果触发IncorrectResultSizeDataAccessException。 |
Stream |
|
Streamable |
Iterable的便利扩展,直接将方法公开到流、映射和过滤结果,将它们串联等 |
Slice |
分片 |
Page |
分页 |
repository与mongoTemplate区别
MongoRepository继承了CRUDCrudRepositorys对于查询操作有默认的抽象类方法,查询或者分页操作使用方便,但是对于修改或者删除数据扩展不太好
Repository: 仅仅是一个标识,表明任何继承它的均为仓库接口类
CrudRepository: 继承 Repository,实现了一组 CRUD 相关的方法
PagingAndSortingRepository: 继承 CrudRepository,实现了一组分页排序相关的方法
MongoRepository: 继承 PagingAndSortingRepository,实现一组 mongodb规范相关的方法
MongoRepository的缺点是不够灵活,也不能够灵活了,所以但是对于稍微复杂的查询,使用mongoTemplate更为方便,代码更易读
如果控制台需要打印mogodb查询语句可在配置文件中添加日志级别为debug:
logging:
level:
org:
springframework:
data:
mongodb:
core: DEBUG
⚠️注意事项
1、如果查询结果使用实体类接受如BookInfo或者Optional一定要确保结果唯一,如果有多条会抛出returned non unique result异常,如果不确定多条,可以排序之后使用Top或者First进行条数限制 2、分页查询PageRequest.of(1, 10)表示查询第二页的10条数据,要注意这里的page实际上是从0开始的,如查询第一页10条PageRequest.of(0, 10),如果一般情况下不需要第二页了简介写法为PageRequest.of(4),表示所有分页前四条结果
3、像客户端查询接口不需要知道总共有多少页,只需要知道是否有下一页,可以使用Slice接受,减少count查询
4、如果查询出来的结果为List,且需要对这个list进行进一步的循环操作,请直接使用Iterable<>或Streamable<>接受,减少循环次数
参考文档
https://www.mongodb.com/
https://docs.mongoing.com/mongodb-crud-operations
https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#repositories.custom-implementations