我是 MongoDB 新手。我有一个类似的集合:
[
{
"_id":"1",
"travels":[
{
"_id":"1"
},
{
"_id":"2"
},
{
"_id":"3"
}
]
},
{
"_id":"2",
"travels":[
{
"_id":"4"
},
{
"_id":"5"
},
{
"_id":"6"
}
]
}
]
我的 Java 模型或多或少是这样的(为了简单起见,使用公共修饰符):
public class TravelsDocument<T> {
@Id
public String id;
public List<Travel> travels;
}
public class Travel {
public String id;
}
travels 数组中的所有 id 都是唯一的。在我的 Spring 应用程序中,我想选择与指定 id 匹配的单个
travel
元素。
我终于弄清楚如何在 MongoDB 中做到这一点。 首先,我应用了过滤器:
{travels: {$elemMatch: { _id: 'someId'}}}
然后是投影:
{
"_id":0,
"travel":{
"$arrayElemAt":[
"$travels",
{
"$indexOfArray":[
"$travels._id",
"someId"
]
}
]
}
}
然后我尝试在聚合中使用它:
@Aggregation(pipeline = {
"{'$match' :{'travels': {$elemMatch: { _id: :#{#id}}}}}",
"{'$project' :{_id:0, 'travel':{$arrayElemAt: [ '$travels', {$indexOfArray :['$travels._id', :#{#id}]} ] }}}"})
Mono<Travel> findSingleTravelByTenantAndId(@Param("id") String id);
问题是这个方法不返回我的
Travel
对象,而是返回 org.bson.Document
对象。有没有办法使用聚合注释返回我的自定义对象?这是要走的路吗?
聚合管道的最终投影阶段将返回文档为
{ travel: { _id: 123 } }
- 请注意外部 travel
字段。但这不是您的 Travel
类的结构,它只定义 id
(我认为映射到 _id
),可能还有其他字段/成员。
所以你需要添加一个
$replaceWith
阶段:
{ $replaceWith: "$travel" }
或者更好的是,删除项目阶段并使用replaceWith代替:
{
$replaceWith: {
"$arrayElemAt":[
"$travels",
{
"$indexOfArray":[
"$travels._id",
"someId"
]
}
]
}
}
所以完整的管道将是:
db.collection.aggregate([
{
$match: {
travels: { $elemMatch: { _id: "someId" } }
}
},
{
$replaceWith: {
$arrayElemAt: [
"$travels",
{ $indexOfArray: ["$travels._id", "someId"] }
]
}
}
])