场景:MongoDB表中的某字段数据量非常大,需要限制只返回该字段 【最新】 的2000条数据
数据结构:datas字段中的数据,根据时间排序如下,最新的数据排在文档的最底下
{
...
"userid" : "123",
"datas" : [
{
"id" : "111",
"time" : ISODate("2019-05-20T08:12:13.058+0000")
},
{
"id" : "222",
"time" : ISODate("2019-05-21T02:49:57.090+0000")
},
{
"id" : "333",
"time" : ISODate("2019-05-22T07:19:13.022+0000")
},
...
],
...
}
前提:
Java MongoTemplate查询返回【内嵌集合】指定数量的数据,核心代码:
详情查看:https://blog.csdn.net/weixin_41888813/article/details/96995155
问题:以下代码可以获取到datas集合中【0,2000】的数据,从旧数据开始截取,并不是最新数据
// one 标记
MongoCollection<Document> collection =
mongoClient.getDatabase(YOUR_DATABASE_NAME).getCollection(YOUR_COLLECTION_NAME);
// two 标记
FindIterable<Document> findIterable = collection.find()
.filter(eq("userid", userid))
.projection(fields(include("datas"), excludeId(), slice("datas", 2000)));
// three 标记
Document resultDocument = findIterable.first();
if (document != null) {
entity = Tools.json2Object(Tools.bulidJSON(resultDocument), Entity.class);
}
思路一:查询中加入嵌套集合内容排序,改动 two 标记处的代码:嵌套文档无法进行排序,行不通
详情查看:https://blog.csdn.net/weixin_41888813/article/details/97117784
// two
FindIterable<Document> findIterable = collection.find()
.filter(eq("userid", userid))
// .sort(Sorts.descending("datas.createtime"))
// .sort(Sorts.orderBy(Sorts.descending("datas.createtime")))
// .sort(new Document("datas.createtime", -1))
.projection(fields(include("datas"), excludeId(), slice("datas", 2000)));
思路二:使用unwind拆分集合再聚合拼装,性能消耗问题,行不通
// Aggregation agg = newAggregation(
// unwind("datas"),
// project("userid", userid)
// );
// AggregationResults<Document> result = mongoTemplate.aggregate(agg, Document.class);
// Document document = result.getMappedResults().get(0);
思路三:发现 two 标记处的 【slice()】可传入跳过元素数,那么需要先获取出datas字段的长度
skip @param limit the number of elements to project 应用此限制之前要跳过的元素数
/**
* Creates a projection to the given field name of a slice of the array value of that field.
*
* @param fieldName the field name
* @param skip the number of elements to skip before applying the limit
* @param limit the number of elements to project 应用此限制之前要跳过的元素数
* @return the projection
* @mongodb.driver.manual reference/operator/projection/slice Slice
*/
public static Bson slice(final String fieldName, final int skip, final int limit) {
return new BsonDocument(fieldName, new BsonDocument("$slice", new BsonArray(asList(new BsonInt32(skip), new BsonInt32(limit)))));
}
第一步:获取出datas字段的长度
法一详情:https://blog.csdn.net/weixin_41888813/article/details/97149494
spring-data-mongodb 包需要 2.1.1.RELEASE的版本,但项目底层用了旧版封装MongoDB代码,引入新依赖,底层代码报错
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
法二详情:https://blog.csdn.net/weixin_41888813/article/details/97114714
获取到内嵌的集合的数据大小后,传入到 two 标记的第二个参数中,加入处理,实现查询出最新的2000条数据