Mongodb Mongo DB按日期排序和按标记分组
我有一个类似以下内容的Mongo DB集合:Mongodb Mongo DB按日期排序和按标记分组,mongodb,jpa,spring-data-jpa,mongodb-query,Mongodb,Jpa,Spring Data Jpa,Mongodb Query,我有一个类似以下内容的Mongo DB集合: { "_id": "...", "name": "name 1", "created": "2020-07-21T08:11:18.414+00:00", "tags": ["red", "green"] } { "_id&
{
"_id": "...",
"name": "name 1",
"created": "2020-07-21T08:11:18.414+00:00",
"tags": ["red", "green"]
}
{
"_id": "...",
"name": "name 2",
"created": "2020-07-20T08:11:18.414+00:00",
"tags": ["red", "blue"]
}
{
"_id": "...",
"name": "name 3",
"created": "2020-07-19T08:11:18.414+00:00",
"tags": ["green", "blue"]
}
{
"_id": "...",
"name": "name 4",
"created": "2020-07-18T08:11:18.414+00:00",
"tags": ["white", "blue"]
}
{
"_id": "...",
"name": "name 5",
"created": "2020-07-17T08:11:18.414+00:00",
"tags": ["white", "green"]
}
{
"red": {
"_id": "...",
"name": "name 1",
"created": "2020-07-21T08:11:18.414+00:00",
"tags": ["red", "green"]
},
"green": {
"_id": "...",
"name": "name 1",
"created": "2020-07-21T08:11:18.414+00:00",
"tags": ["red", "green"]
},
"blue": {
"_id": "...",
"name": "name 2",
"created": "2020-07-20T08:11:18.414+00:00",
"tags": ["red", "blue"]
}
}
我需要能够指定标记列表,并且对于列表中的每个标记,我需要获取最近创建的文档。在上面的示例中,如果我指定[“红色”、“绿色”、“蓝色”]
,我将得到类似的结果:
{
"_id": "...",
"name": "name 1",
"created": "2020-07-21T08:11:18.414+00:00",
"tags": ["red", "green"]
}
{
"_id": "...",
"name": "name 2",
"created": "2020-07-20T08:11:18.414+00:00",
"tags": ["red", "blue"]
}
{
"_id": "...",
"name": "name 3",
"created": "2020-07-19T08:11:18.414+00:00",
"tags": ["green", "blue"]
}
{
"_id": "...",
"name": "name 4",
"created": "2020-07-18T08:11:18.414+00:00",
"tags": ["white", "blue"]
}
{
"_id": "...",
"name": "name 5",
"created": "2020-07-17T08:11:18.414+00:00",
"tags": ["white", "green"]
}
{
"red": {
"_id": "...",
"name": "name 1",
"created": "2020-07-21T08:11:18.414+00:00",
"tags": ["red", "green"]
},
"green": {
"_id": "...",
"name": "name 1",
"created": "2020-07-21T08:11:18.414+00:00",
"tags": ["red", "green"]
},
"blue": {
"_id": "...",
"name": "name 2",
"created": "2020-07-20T08:11:18.414+00:00",
"tags": ["red", "blue"]
}
}
我的问题是:
聚合操作
我很高兴能对问题1给出一个好的答案,我也可以单独寻找问题2的答案。正如您所提到的,您可以通过聚合来实现这一点
$sort
按降序创建的$facet
帮助对内部文档进行分类,我们使用$match
过滤标记$project
有助于投影。我们已经按创建的排序了。因此,我们将通过$arrayElemAt
获取第一个元素,有时如果没有元素,它将抛出异常,因此为了返回空对象,我们使用$ifNull
[
{
$sort: {
created: -1
}
},
{
$facet: {
red: [
{
$match: {
tags: "red"
}
}
],
green: [
{
$match: {
tags: "green"
}
}
],
blue: [
{
$match: {
tags: "blue"
}
}
]
}
},
{
$project: {
red: {
$ifNull: [
{
"$arrayElemAt": [
"$red",
0
]
},
{}
]
},
blue: {
$ifNull: [
{
"$arrayElemAt": [
"$blue",
0
]
},
{}
]
},
green: {
$ifNull: [
{
"$arrayElemAt": [
"$green",
0
]
},
{}
]
}
}
}
]
工作
当我们将其转换为Spring数据时
public List<Object> test() {
Aggregation aggregation = Aggregation.newAggregation(
sort(Sort.Direction.DESC, "created"),
facet(
match(Criteria.where("tags").is("red"))
).as("red")
.and(
match(Criteria.where("tags").is("green"))
).as("green")
.and(
match(Criteria.where("tags").is("blue"))
).as("blue"),
project()
.and(ConditionalOperators.ifNull(ArrayOperators.arrayOf("red").elementAt(0)).then(new Document())).as("red")
.and(ConditionalOperators.ifNull(ArrayOperators.arrayOf("blue").elementAt(0)).then(new Document())).as("blue")
.and(ConditionalOperators.ifNull(ArrayOperators.arrayOf("green").elementAt(0)).then(new Document())).as("green")
).withOptions(AggregationOptions.builder().allowDiskUse(Boolean.TRUE).build());
return mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(YOUR_COLLECTION.class), Object.class).getMappedResults();
}
公共列表测试(){
Aggregation=Aggregation.newAggregation(
排序(sort.Direction.DESC,“已创建”),
小平面(
匹配(标准,其中“标签”为“红色”)
).as(“红色”)
.及(
匹配(标准,其中“标签”为“绿色”)
).as(“绿色”)
.及(
匹配(标准。其中(“标签”)为(“蓝色”))
).以“蓝色”命名,
项目()
和(ConditionalOperators.ifNull(ArrayOperators.arrayOf(“红色”).elementAt(0))。然后(new Document()).as(“红色”)
和(ConditionalOperators.ifNull(ArrayOperators.arrayOf(“蓝色”).elementAt(0))。然后(new Document()).as(“蓝色”)
和(ConditionalOperators.ifNull(ArrayOperators.arrayOf(“绿色”).elementAt(0))。然后(new Document()).as(“绿色”)
).withOptions(AggregationOptions.builder().allowDiskUse(Boolean.TRUE.build());
返回mongoTemplate.aggregate(聚合,mongoTemplate.getCollectionName(您的_COLLECTION.class),Object.class).getMappedResults();
}
注意:我还没有在spring boot中测试上述代码。但它是基于mongo脚本编写的。希望它能起作用。谢谢!我会测试一下,让你知道我也在找同样的。如果您成功使用此解决方案,请与我们分享。@varman测试成功(包括java代码),谢谢