Mongodb 如何让Spring数据Mongo聚合像使用Mongo一样工作
我正在尝试使用SpringDataMongo的聚合API进行一个简单的投影 我想做的管道步骤是:Mongodb 如何让Spring数据Mongo聚合像使用Mongo一样工作,mongodb,aggregation-framework,spring-data-mongodb,Mongodb,Aggregation Framework,Spring Data Mongodb,我正在尝试使用SpringDataMongo的聚合API进行一个简单的投影 我想做的管道步骤是: { $project : { "account._id" : 1, "account.position" : 1 } } 这是我尝试过的,还有很多其他的调整,因为似乎什么都不起作用: ProjectionOperation project1 = Aggregation.project("account._id", "account.position"); 然而,尽管文档中
{
$project : {
"account._id" : 1,
"account.position" : 1
}
}
这是我尝试过的,还有很多其他的调整,因为似乎什么都不起作用:
ProjectionOperation project1 = Aggregation.project("account._id", "account.position");
然而,尽管文档中说要在这里实现这一点:
由该投影呈现的实际文档最终看起来像:
{
$project : {
_id : "$account._id",
position : "$account.position"
}
}
它的工作原理与我想要使用的投影完全不同
有人知道如何从SpringDataMongo聚合API中获得我想要的投影吗?或者这是我需要报告的一个bug吗
2019年8月29日更新-添加更多数据以构建上下文:
涉及两个集合:组和帐户
一个组看起来像这样:
{
_id : ObjectId("..."),
name: ...,
ownerId: ObjectId("..."),
other stuff...
}
{
_id : ObjectId("..."),
position : "ABC",
memberships : [{
groupId: ObjectId("..."),
otherstuff: ...,
}],
other stuff...
}
帐户的外观如下所示:
{
_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")
);
您可以用更通用的方式检查我的答案您是否可以共享所涉及的域类型以及整个聚合,而不仅仅是一个项目操作。在类型化聚合的情况下,属性映射到字段名。@christofstrobl,我在问题中添加了其他信息。是的,我知道我可以这样做。我考虑将整个聚合编写为json,因为这就是我开发管道并解析它以运行的方式,但我正在尝试通过SpringAggregationAPI解决这个问题。