英文:
Is there any in-built function in spring mongo which can be used to extract data from two different documents having onetoone relationship?
问题
我只是在使用 Spring 中的 Mongo Template 从两个不同的 MongoDB 文档中提取数据,这两个文档具有一对一的关系。
我有两个文档 "Rosters"(属于用户的嵌入式文档)和 "Unread",它们都由 "ucid"(唯一会话标识符的首字母缩写)来标识。基于 ucid,我想执行内连接操作并提取数据。
有许多示例是针对一对多关系使用查找(lookup)和聚合(aggregation),但没有针对一对一关系的。
以下是类的定义:
User
class User {
private List<Roster> rosterList;
}
Roster
public class Roster extends Parent {
@Id
private ObjectId _id;
@Indexed
private String author;
@Unique
private String ucid;
}
Unread
public class Unread {
@Id
@Indexed(unique=true) //todo: 在 MongoDB 上创建索引
private String ucid;
private Map<String, Long> memberAndCount;
}
示例数据:
用户(roster):
{
user: {
id: 1001,
username: "dilag",
roster: [
{ ucid: "r0s122", name: "sam" },
{ ucid: "r0s123", name: "ram" },
{ ucid: "r0s124", name: "rat" }
]
}
}
未读(unread):
{
ucid: "r0s122",
usernameAndCount: [
{ username: "dilag", count: 100 },
{ username: "ramg", count: 20 }
]
},
{
ucid: "r0s123",
usernameAndCount: [
{ username: "dilag", count: 100 },
{ username: "ramg", count: 20 }
]
}
期望的输出:
{
ucid: "r0s122",
name: "sam",
usernameAndCount: [
{ username: "dilag", count: 100 },
{ username: "ramg", count: 20 }
]
},
{
ucid: "r0s123",
name: "ram",
usernameAndCount: [
{ username: "dilag", count: 100 },
{ username: "ramg", count: 20 }
]
}
英文:
I am just looking for extracting data from two different documents in mongodb having onetoone relationship using Mongo Template in spring.
I have two documents "Rosters" (Embedded Document belonging to User) and "Unread" both are identified by "ucid" an acronym for "unique conversation identifier". On the basis of ucid i'd like to perform inner-join operation and extract the data.
There are ample examples where lookup and aggregations are used for OneToMany Relationship but not for OnetToOne.
Following are the class
**User**
class User
{
private List<Roster> rosterList;
}
**Roster**
public class Roster extends Parent
{
@Id
private ObjectId _id;
@Indexed
private String author;
@Unique
private String ucid;
}
**Unread**
public class
{
@Id
@Indexed(unique=true) //todo: create index on mongo side as well
private String ucid;
private Map<String,Long> memberAndCount;
}
----------------------------------------------------
Sample Data:
USER (roster)
{user:{id:1001, username: dilag,roster:
[{
ucid:r0s122,name:sam}
},{
ucid:r0s123,name:ram}
},{
ucid:r0s124,name:rat}
}]}
UNREAD
{
ucid:r0s122,usernameAndCount:[{username:dilag,count:100},{username:ramg,count:20}],
ucid:r0s123,usernameAndCount:[{username:dilag,count:100},{username:ramg,count:20}]
}
Desired Output
{
ucid:r0s122, name :sam,usernameAndCount:[{username:dilag,count:100},{username:ramg,count:20}],
ucid:r0s123,name:ram,usernameAndCount:[{username:dilag,count:100},{username:ramg,count:20}]
}
答案1
得分: 1
以下是翻译好的部分:
下面的 Spring 代码尚未经过测试,但是基于可工作的 Mongo Playground 编写而成。
基本上你需要了解在 MongoDB 中使用 $lookup
进行连接操作。在这里,我使用了无关联子查询的连接方式。
public List<Object> test() {
Aggregation aggregation = Aggregation.newAggregation(
l -> new Document("$lookup",
new Document("from","user")
.append("let", new Document("uid","$uicd"))
.append("pipeline",
Arrays.asList(
new Document("$unwind", "$user.roster"),
new Document("$match",
new Document("$expr",
new Document("$eq",Arrays.asList("$user.roster.ucid","$$uid"))
)
)
)
).append("as","users")
),
a -> new Document("$addFields",
new Document("name",
new Document("$ifNull",
Arrays.asList(
new Document("$arrayElemAt", Arrays.asList("$users.user.roster.name",0))
,
"")
)
)
)
).withOptions(AggregationOptions.builder().allowDiskUse(Boolean.TRUE).build());
return mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(Unread.class), Object.class).getMappedResults();
}
阅读此链接以了解如何在 MongoDB Spring Data 中使用 new Document()
进行聚合操作的技巧。
英文:
The following spring code is not tested, But it's written based on working Mongo playground.
Basically you need to know about joining in Mongodb using $lookup
. Here I have used Joining Uncorrelated Sub-queries
public List<Object> test() {
Aggregation aggregation = Aggregation.newAggregation(
l-> new Document("$lookup",
new Document("from","user")
.append("let", new Document("uid","$uicd"))
.append("pipeline",
Arrays.asList(
new Document("$unwind", "$user.roster"),
new Document("$match",
new Document("$expr",
new Document("$eq",Arrays.asList("$user.roster.ucid","$$uid"))
)
)
)
).append("as","users")
),
a-> new Document("$addFields",
new Document("name",
new Document("$ifNull",
Arrays.asList(
new Document("$arrayElemAt", Arrays.asList("$users.user.roster.name",0))
,
""
)
)
)
)
).withOptions(AggregationOptions.builder().allowDiskUse(Boolean.TRUE).build());
return mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(Unread.class), Object.class).getMappedResults();
}
Read this to understand the trick how to do aggregation if mongo spring-data doesn't provide any operation using new Document()
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论