【发布时间】:2022-11-26 05:59:46
【问题描述】:
假设我的产品集合包括每个产品都有如下数组项的产品。
[
{
"_id": "1",
"score": 200,
"items": [
{
"_id": "1",
"title": "title1",
"category": "sport"
},
{
"_id": "2",
"title": "title2",
"category": "sport"
},
{
"_id": "3",
"title": "title3",
"category": "tv"
},
{
"_id": "4",
"title": "title4",
"category": "movies"
}
]
},
{
"_id": "2",
"score": 1000000000,
"items": [
{
"_id": "9",
"title": "titleBoo",
"category": "food"
},
{
"title": "title4",
"category": "movies"
},
{
"title": "titlexx",
"category": "food"
},
{
"title": "titl113",
"category": "sport"
}
]
},
{
"_id": "3",
"score": 500,
"items": [
{
"title": "title3",
"category": "movies"
},
{
"title": "title3",
"category": "food"
},
{
"title": "title3",
"category": "sport"
},
{
"title": "title3",
"category": "sport"
}
]
}
]
我想按类别返回具有最高得分的类别的单个项目,如果没有匹配的类别,则只返回具有最高得分的随机/第一个产品。
类别“食品”的示例,结果应为:
{
"_id" : "9",
"title": "titleBoo",
"category": "food"
}
因为它的最高分是1000000000
对于其他不存在的类别“Foo”,结果应该是从得分最高的产品项目中随机抽取的,比方说
{
"title": "titlexx",
"category": "food"
},
基本上我使用 java spring 数据聚合管道所做的
Aggregation agg1 = newAggregation(
unwind("items"),
match(Criteria.where("items.category").is(category)),
group().max("score").as("score")
);
BasicDBObject result = mongoTemplate.aggregate(
agg1, "products", BasicDBObject.class).getUniqueMappedResult();
if (result empty) { // didn't find any matched category so without match step !
Aggregation agg2 = newAggregation(
unwind("items"),
group().max("score").as("score")
);
// take some item inside max "score"
BasicDBObject res2 = mongoTemplate.aggregate(
agg2, "products", BasicDBObject.class).getUniqueMappedResult();
System.out.print(res2);
}
这段代码不理想,因为我需要执行两次“unwind”(如果不匹配)再做一次。我知道有 $cond / switch 函数,我想知道我是否可以在 unwind 之后使用一些 switch case 操作像这儿:
Aggregation agg = newAggregation(
unwind("items"),
// switch-case {
a. match(Criteria.where("items.category").is(category)),
if (result or size > 0) {
group().max("score").as("score") // max on matched result by category
}
b. group().max("score").as("score"). // max on random unwind score
}
);
BasicDBObject result = mongoTemplate.aggregate(
agg, "products", BasicDBObject.class).getUniqueMappedResult();
有什么提示吗?
【问题讨论】:
-
考虑做一个
$sort和$limit而不是分组以获得最大值。还要确保score是一个数字而不是真实数据集中的字符串。 -
谢谢@user20042973,编辑我的问题,确定分数是数字(长),放松和匹配怎么样?如果没有匹配项,我如何减少两次 unwind 调用 ...
标签: mongodb mongodb-query spring-data spring-data-mongodb