mongodb - 如何让 Spring Data Mongo 聚合像使用 mongo 一样工作
问题描述
我正在尝试使用 Spring Data Mongo 的聚合 API 进行简单的投影。
我想做的管道步骤是:
{
$project : {
"account._id" : 1,
"account.position" : 1
}
}
这是我尝试过的(以及大量其他调整,因为似乎没有任何效果):
ProjectionOperation project1 = Aggregation.project("account._id", "account.position");
但是,即使这是文档所说的方法: https ://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mongo.aggregation.projection
该投影呈现的实际文档最终看起来像:
{
$project : {
_id : "$account._id",
position : "$account.position"
}
}
这与我想要使用的投影完全不同。
有谁知道如何从 Spring Data Mongo Aggregation API 中获得我想要的投影,或者这是我需要报告的错误?
2019 年 8 月 29 日更新 - 添加更多数据以构建上下文:
涉及两个集合:“组”和“帐户” 组看起来像这样:
{
_id : ObjectId("..."),
name: ...,
ownerId: ObjectId("..."),
other stuff...
}
一个帐户看起来像这样:
{
_id : ObjectId("..."),
position : "ABC",
memberships : [{
groupId: ObjectId("..."),
otherstuff: ...,
}],
other stuff...
}
我的整个聚合看起来像这样,并在 mongodb shell 中按需要工作:(尝试获取特定类型的所有帐户 ID 的列表,这些帐户 ID 是特定用户拥有的任何组的成员)
groups.aggregate(
{
$match : {
ownerId : ObjectId("XYZ"),
}
},
{
$lookup: {
from: "accounts",
localField: "_id",
foreignField: "memberships.groupId",
as: "account"
}
},
{
$project: {
"account._id" : 1,
"account.position" : 1
}
},
{
$unwind: "$account"
},
{
$match: {
"account.position" : "ZZZ"
}
},
{
$project: {
_id : 0,
accountId : "$account._id"
}
})
聚合的 Java 版本:
MatchOperation match1 = Aggregation.match(
where("ownerId").is(accountId));
LookupOperation lookupOperation = LookupOperation.newLookup()
.from("accounts")
.localField("_id")
.foreignField("memberships.groupId")
.as("account");
// This doesn't work correctly on nested fields:
ProjectionOperation project1 = Aggregation.project(
"studentAccount._id",
"studentAccount.position");
Aggregation aggregation = Aggregation.newAggregation(
match1,
lookupOperation,
project1,
unwind("account"),
match(where("account.position").is("ZZZ")),
project().and("account._id").as("accountId"));
解决方案
如果您希望您的聚合工作看起来像 mongoshell,您可以尝试这样
Aggregation aggregation = Aggregation.newAggregation(
match1,
lookupOperation,
// This's your project operation
new AggregationOperation() {
@Override
public Document toDocument(AggregationOperationContext aggregationOperationContext) {
Document project = new Document("$project",
new Document(
"_id", "$account._id"
).append("position", "$account.position")
);
return aggregationOperationContext.getMappedObject(project);
}
},
unwind("account"),
match(where("account.position").is("ZZZ")),
project().and("account._id").as("accountId")
);
您可以在此处以更通用的方式查看我的答案
推荐阅读
- ant-media-server - 如何减少 Ant Media Server 中的日志大小?
- reporting-services - Power BI (SSRS) Report Builder 从第 1 列向下钻取到第 2 列 - 如何确保始终显示第 3 列?
- php - 获取活跃货币和未设置国家 WooCommerce
- aws-glue - py4j.protocol.Py4JJavaError: 调用 o133.pyWriteDynamicFrame 时出错
- javascript - java和Javascript的通用正则表达式
- elf - 不连贯的程序头和扇区头
- excel - Wraptext() 函数不适用于变量
- oracle - 创建临时用户帐户 oracle apex
- java - CodenameOne - iOS 上库文件夹的文件系统访问问题
- python - 无法下载 face_recognition 包