写在最前:

因业务需要,需要在mongodb操作数据,mongodb数据格式为带数组array的文档行,现有需求如下:
查询数组中半年或者一年不活跃的数据和活跃的数据(以时间小于多少为准),大量查官方文档,民间野文后终解决问题。

思路为:
半年之内的为活跃数据,半年以前的为不活跃数据,不活跃数据为数组中所有元素的对应值都超过半年,但mongodb查询默认任一元素对应值匹配条件就算查询到,现解决数组内任一元素对应值不满足就放弃整个文档行问题。

数据格式:

{
	"_id" : ObjectId("5fc4646a2b7bfb044c042e52"),
	"UNISCID" : 1,
	"ACTIVESTATELIST" : [
		{
			"createTime" : "2022-02-09 00:00:00.000",
			"state" : 2
		},
		{
			"createTime" : "2022-02-09 00:00:00.000",
			"state" : 5
		},
		{
			"createTime" : "2022-02-09 00:00:00.000",
			"state" : 1
		}
	]
}
{
	"_id" : ObjectId("5fc4646a2b7bfb044c042e53"),
	"UNISCID" : 2,
	"ACTIVESTATELIST" : [
		{
			"createTime" : "2021-08-09 00:00:00.000",
			"state" : 2
		},
		{
			"createTime" : "2021-08-09 00:00:00.000",
			"state" : 4
		},
		{
			"createTime" : "2021-08-09 00:00:00.000",
			"state" : 1
		}
	]
}

1.活跃数据

db.getCollection("文档名").find({"ACTIVESTATELIST.createTime" : { $gte : ISODate("2022-02-09 00:00:00.000") }}).limit(1000).skip(0)

java:
Query query = new Query();
Criteria c = new Criteria();
c.and(ACTIVESTATELIST_CREATETIME).gte(LocalDateTime.now().minusMonths(6));
query.addCriteria(c);
long count = mongoTemplate.count(query, "文档名");

2.半年/一年不活跃数据(核心思想:两次否定得出肯定,首先筛选出数组中所有数据的createTime都大于半年前的,然后取反即可。若是具体的字段就用$nin,这里还有DISTRICT和ENTERPRISETYPE两个条件)

db.getCollection("ENTERPRISE_LIVENESS_MODEL").find({
    "DISTRICT": {
        "$regex": "510101.*",
        "$options": ""
    },
    "ENTERPRISETYPE": "0",
    "ACTIVESTATELIST": {
        "$not": {
            "$elemMatch": {
                "createTime": {
                    "$gte": {
                        "$date": 1628494391512
                    }
                }
            }
        }
    }
})

java:
Query query = new Query();
Criteria c = new Criteria();
c.and(DISTRICT).regex(district + ".*");
c.and("ENTERPRISETYPE").is("0");
//半年
c.and("ACTIVESTATELIST").not().elemMatch(Criteria.where("createTime").gte(LocalDateTime.now().minusMonths(6)));
//一年
c.and("ACTIVESTATELIST").not().elemMatch(Criteria.where("createTime").gte(LocalDateTime.now().minusMonths(12)));
query.addCriteria(c);
long count = mongoTemplate.count(query, "文档名");

注:查出来后半年前的数据会包含一年前的数据,而不是一年前包含半年前数据,如不想包含可再附上限制条件。

另:
有多个条件时java代码拼接,这里为not like条件

List<Criteria> listist = new ArrayList<>();
List<String> sqList = new ArrayList<>();
for (String s : sqList) {
    Criteria ccc = new Criteria();
    ccc.and("字段名").not().regex(s + ".*");
    criteriaList.add(ccc);
}
Criteria ccc = new Criteria();
ccc.and(DISTRICT).regex("模糊匹配值" + ".*");
criteriaList.add(ccc);
c.andOperator(criteriaList.toArray(new Criteria[criteriaList.size()]));
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐