前言:mongodb对复杂查询并不友好,尤其是关于时间的查询更甚。本篇主要针对常见的查询进行汇总。

关于springboot和mongodb的整合可看此篇,本篇是延伸。

1,普通列表查询 (MongoRepository)

 //service层

   public List<TkLogMg> listByIssue(String issue) {
		Sort sort = Sort.by(Sort.Direction.ASC, "code");
		return tkLogMgDao.findByIssue(issue, sort);
    }

//dao层
public interface TkLogMgDao extends MongoRepository<TkLogMg, String>{

	List<TkLogMg> findByIssue(String issue, Sort sort);
}

Sort为排序类:Sort.Direction.ASC 升序,Sort.Direction.DESC 倒序。第二个参数可为多个,则是顺序排序,类似mysql的 order by 字段1,字段2  desc

2,关于时间查询的列表 (MongoRepository)

//service层
public List<TkLogMg> listCurr() {
		Sort sort = Sort.by(Sort.Direction.DESC, "sort");
		return tkLogMgDao.findByDtAfter(DateUtil.date().toJdkDate(), sort);
}

public List<TkLogMg> listOver() {
		Sort sort = Sort.by(Sort.Direction.DESC, "dt");
		Date nowDate = DateUtil.offsetHour(DateUtil.date(), 2);
		List<TkLogMg> overMatchList = tkLogMgDao.findByStateAndDtBefore(1, nowDate, sort);
		return overMatchList;
}

//dao层
List<TkLogMg> findByDtAfter(Date nowDate, Sort sort);

List<TkLogMg> findByStateAndDtBefore(Integer state, Date nowDate, Sort sort);

其中dt是一个时间字段,state是一个状态字段。

after为大于,where dt>?

before为小于, where dt<?

但是遇到一个问题,如果需要查询时间区间,则使用此方式会发生运行时异常。

所以时间区间查询,需要使用mongoTemplate,代码如下:

public List<TkLogMg> listByBeginEnd(Date begin, Date end) {
		Sort sort = Sort.by(Sort.Direction.DESC, "dt");
//		return matchLotMgDao.findByDtBeforeAndDtAfter(begin, end, sort); 
		Criteria criteria = new Criteria();
		criteria.and("dt").gte(begin).lte(end);
		Query query = new Query();
		query.addCriteria(criteria);
		query.with(sort);
		return mongoTemplate.find(query, TkLogMg.class);
	}

gte为大于并且等于,gt为大于

lte为小于并且等于,lt为小于

3,普通分页(MongoRepository)

public Page<TkLogMg> page(Integer currPage, Integer pageSize, TkLogMg queryMg) {
		Sort sort = Sort.by(Sort.Direction.DESC, "issue","code");
		PageRequest pageRequest = PageRequest.of(currPage - 1, pageSize, sort);
		TkLogMg tmMg = new TkLogMg();
		BeanUtils.copyProperties(queryMg, tmMg);
		ExampleMatcher matcher = ExampleMatcher.matching().withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) // 改变默认字符串匹配方式:模糊查询
				.withIgnoreCase(true) // 改变默认大小写忽略方式:忽略大小写
				.withMatcher("issue", ExampleMatcher.GenericPropertyMatchers.contains())
				.withMatcher("code", ExampleMatcher.GenericPropertyMatchers.contains()); // 采用“包含匹配”的方式查询
//                .withIgnorePaths("pageNum", "pageSize");  //忽略属性,不参与查询;
		Example<TkLogMg> example = Example.of(tmMg, matcher);
		Page<TkLogMg> all = tkLogMgDao.findAll(example, pageRequest);
		return all;
	}

这是一个普通的分页,字段模糊查询。需注意:对象必须在此方法中转换

4,关于时间等复杂条件的分页查询(mongoTemplate)

若是分页查询中涉及到时间,使用MongoRepository,会发现出来的结果并不如预期。可使用如下方式进行:

public Page<TkLogMg> page2(Integer currPage, Integer pageSize, TkLogMg queryMg) {
		Query query = new Query();
		Criteria criteria = new Criteria();
		if (StringUtils.isNotEmpty(queryMg.getLn())) {
			criteria.and("ln").is(queryMg.getLn());
		}
		if (queryMg.getState() != null && queryMg.getState() != 0) {
			criteria.and("state").is(queryMg.getState());
		}
		criteria.and("dt").lte(DateUtil.date().toJdkDate());
		query.addCriteria(criteria);
		Sort sort = Sort.by(Sort.Direction.DESC, "dt");
		query.with(sort);
		Pageable pageable = PageRequest.of(currPage - 1, pageSize);
		query.with(pageable);
		List<MatchLotMg> resolveRules = mongoTemplate.find(query, TkLogMg.class);
		return PageableExecutionUtils.getPage(resolveRules, pageable,
				() -> mongoTemplate.count(query, MatchLotMg.class));
	}

5,外键查询(mongoTemplate)

当实体的数据结构如下时:

@Data
@Document(collection = "test_traito")
public class TraitMg {
	@Id
	private String id;
	private String traitEn;
	
	@DBRef
	private MatchLotMg match;

	private Date uptDate;
}

@Data
@Document(collection="test_match")
public class MatchMg {
	@Id
    private String id;		
	private Integer dmId;
	
	private String hn;
	private String an;
	private Date dt;

	private Date uptDate;
}

注意traitMg中映射了另外一个实体对象match。此时若想简单通过trait查询match,是只能通过match的id查询的,若想通过match中的其他字段查询会报运行时异常。简单查询代码如下:

public List<TraitMg> listByMatchId(String matchId) {
		Sort sort = Sort.by(Sort.Direction.DESC, "sort");
		Query query = new Query();
		query.addCriteria(Criteria.where("match.id").is(matchId));
		query.with(sort);
		return mongoTemplate.find(query, TraitMg.class);
}

若想通过match的其他字段查询,则需要做实体级联,不建议这么做。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐