spring-data-mongodb高级查询用法小结

为什么80%的码农都做不了架构师?>>>   hot3.png

0.准备工作,先介绍下mongodb的集合名,java bean,以及数据结构

  • mongodb集合名称:doc_pageview

  • 集合数据结构:

    	{
    	"_id" : ObjectId("xxxx"),    
    	"shopId" : "xxx",
    	"domain" : "xxxx",
    	"url" : "xxxx",
    	"pageTitle" : "xxx",
    	"pageId" : "xxxx",
    	"cookie" : "xxx",
    	"ip" : "xxxx",
    	"viewDate" : NumberLong(xxxx),
    	"date" : "yyyy-MM-dd",
    	"stayTime" : NumberLong(xxxx)
    	}
    
  • java bean(为保证代码简洁,@Getter、@Setter的注解,使用到lombok):

    	 @Document(collection = "doc_pageview")
    	 @Getter
    	 @Setter
    	public class PageViewBean {
    	    @Id
    	    private String id; //主键
    	    private String domain; //域名
    	    private String url; //相对链接
    	    private String pageTitle; //页面标题
    	    private String pageId; //页面ID
    	    private String cookie;
    	    private Long viewDate; //访问时间(时间戳)
    	    private String shopId; //店铺ID
    	    private String ip; //访问IP
    	    private String date; // 日期:yyyy-MM-dd
    	    private Long stayTime; // 停留时间
    	}
    

1.相关包的引入(笔者使用版本是1.4.0.RELEASE,读者可以选择更高版本)


    org.springframework.boot
    spring-boot-starter-data-mongodb
    1.4.0.RELEASE

2.分页、排序操作

分页排序操作使用org.springframework.data.domain.Pageable,如果根据条件查询,使用注解@Query(org.springframework.data.mongodb.repository.Query)即可。eg:查询cookie=111,date=2017-09-07的前100条记录,按照viewDate倒序(注意实现 MongoRepository接口)

public interface PageViewLogRepository extends MongoRepository {

    /**
     * 根据参数查询日志集合
     * @param cookie
     * @param date
     * @param pageable
     * @return
     */
    @Query("{'cookie':?0,'date':?1}")
    List  findByCookieAndDate(String cookie,String date, Pageable pageable);
}       

测试:

    Pageable pageable = new PageRequest(0, 100, new Sort(Sort.Direction.DESC, "viewDate"));
    Page page = pageViewLogRepository. findByCookieAndDate("111", "2017-09-07", pageable);

3. 聚合操作(分组、求和、平均值、分页、排序)

刚开始尝试使用上面的@Query来做,后来没有发现解决办法(个人认为@Query只是用来处理比较简答的查询,大家如果有,欢迎提出来);本着关系型数据库能做的,mongodb也能做的指导思想,于是尝试新的api;虽然花了点时间,最终还是找到了,核心是org.springframework.data.mongodb.core.aggregation里面的类。其中,Aggregation.newAggregation这个方法是Aggregation的静态方法,支持可变参数,源码如下:

	/**
	 * Creates a new {@link Aggregation} from the given {@link AggregationOperation}s.
	 *
	 * @param operations must not be {@literal null} or empty.
	 */
	public static Aggregation newAggregation(AggregationOperation... operations) {
		return new Aggregation(operations);
	}
	

AggregationOperation是一个接口,很多聚合操作只需实现该接口即可,以下是所有的实现类。 spring-data-mongodb高级查询用法小结_第1张图片 可以猜到SortOperation(排序)、LimitOperation和SkipOperation(分页);好了,现在回到具体问题上面,eg:查询从2017-08-07到2017-09-07一个月店铺的平均单个页面停留时间(总的停留时间/总的pv数),并按从大到小的顺序排序(貌似没啥具体意义,???)

import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;

// 根据avgPvTime=sumStayTime/countPv排序,如下
SortOperation sortOperation = sortOperation = Aggregation.sort(new Sort(Sort.Direction.DESC, "avgPvTime"));

// 根据shopId group查询
Aggregation aggregation = Aggregation.newAggregation(
                            Aggregation.match(Criteria.where("date").gte("2017-08-07").lte("2017-09-07")),
                            Aggregation.group("shopId").sum("stayTime").as("sumStayTime").count().as("countPv"),
                            new ProjectionOperation().andInclude("sumStayTime", "countPv").and("sumStayTime").divide("countPv").as("avgPvTime"),
                            sortOperation,
                            Aggregation.skip(0),
                            Aggregation.limit(100));

转载于:https://my.oschina.net/beanGo/blog/1528234

你可能感兴趣的:(数据库,java,数据结构与算法)