MongoDB - 自加入过滤器
MongoDB - Self join with filter
我有一个合集users
如下:
{ "_id" : ObjectId("570557d4094a4514fc1291d6"), "email": "u1@mail.com", "user_type" : "1", "grade" : "A1", "room_id" : ObjectId("580557d4094a4514fc1291d6") }
{ "_id" : ObjectId("570557d4094a4514fc1291d7"), "email": "u2@mail.com", "user_type" : "2", "grade" : "A2", "room_id" : ObjectId("580557d4094a4514fc1291d6") }
{ "_id" : ObjectId("570557d4094a4514fc1291d8"), "email": "u3@mail.com", "user_type" : "3", "grade" : "A2", "room_id" : ObjectId("580557d4094a4514fc1291d6") }
{ "_id" : ObjectId("570557d4094a4514fc1291d9"), "email": "u4@mail.com", "user_type" : "2", "grade" : "A2", "room_id" : ObjectId("580557d4094a4514fc1291d7") }
{ "_id" : ObjectId("570557d4094a4514fc1291e6"), "email": "u5@mail.com", "user_type" : "3", "grade" : "A1", "room_id" : ObjectId("580557d4094a4514fc1291d7") }
{ "_id" : ObjectId("570557d4094a4514fc1291e7"), "email": "u6@mail.com", "user_type" : "3", "grade" : "A2", "room_id" : ObjectId("580557d4094a4514fc1291d7") }
{ "_id" : ObjectId("570557d4094a4514fc1291e8"), "email": "u7@mail.com", "user_type" : "2", "grade" : "A1", "room_id" : ObjectId("580557d4094a4514fc1291d8") }
{ "_id" : ObjectId("570557d4094a4514fc1291e9"), "email": "u8@mail.com", "user_type" : "3", "grade" : "A1", "room_id" : ObjectId("580557d4094a4514fc1291d8") }
我想找到具有 grade
A2 的类型 2 用户的电子邮件 ID,以及具有相同 room_id
但 user_type
3(grade
确实室友无所谓)。所以结果数据应该是这样的:
{"email": "u2@mail.com", "roommates": [{"email": "u3@mail.com"}]}
{"email": "u4@mail.com", "roommates": [{"email": "u5@mail.com"}, {"email": "u6@mail.com"}]}
如何在 MongoDB 中执行此操作?我有 SQL 的背景,所以我正在考虑自连接,但我想还有其他方法可以做到。
是的,self-join users
合集的(concept/direction)是正确的。
$lookup
- 通过 room_id
和 return roommates
数组加入 users
集合。
$match
- 按 user_type
、grade
和 roommates.user_type
.
过滤文档
$project
- 修饰输出文档。
3.1。 $map
- 迭代 roommates
数组和 return 数组。
3.1.1。 $filter
- 在 roommates
数组中使用 user_type
过滤文档。
db.users.aggregate([
{
$lookup: {
from: "users",
localField: "room_id",
foreignField: "room_id",
as: "roommates"
}
},
{
$match: {
user_type: "2",
grade: "A2",
"roommates.user_type": "3"
}
},
{
$project: {
email: 1,
roommates: {
$map: {
input: {
$filter: {
input: "$roommates",
cond: {
$eq: [
"$$this.user_type",
"3"
]
}
}
},
in: {
email: "$$this.email"
}
}
}
}
}
])
我有一个合集users
如下:
{ "_id" : ObjectId("570557d4094a4514fc1291d6"), "email": "u1@mail.com", "user_type" : "1", "grade" : "A1", "room_id" : ObjectId("580557d4094a4514fc1291d6") }
{ "_id" : ObjectId("570557d4094a4514fc1291d7"), "email": "u2@mail.com", "user_type" : "2", "grade" : "A2", "room_id" : ObjectId("580557d4094a4514fc1291d6") }
{ "_id" : ObjectId("570557d4094a4514fc1291d8"), "email": "u3@mail.com", "user_type" : "3", "grade" : "A2", "room_id" : ObjectId("580557d4094a4514fc1291d6") }
{ "_id" : ObjectId("570557d4094a4514fc1291d9"), "email": "u4@mail.com", "user_type" : "2", "grade" : "A2", "room_id" : ObjectId("580557d4094a4514fc1291d7") }
{ "_id" : ObjectId("570557d4094a4514fc1291e6"), "email": "u5@mail.com", "user_type" : "3", "grade" : "A1", "room_id" : ObjectId("580557d4094a4514fc1291d7") }
{ "_id" : ObjectId("570557d4094a4514fc1291e7"), "email": "u6@mail.com", "user_type" : "3", "grade" : "A2", "room_id" : ObjectId("580557d4094a4514fc1291d7") }
{ "_id" : ObjectId("570557d4094a4514fc1291e8"), "email": "u7@mail.com", "user_type" : "2", "grade" : "A1", "room_id" : ObjectId("580557d4094a4514fc1291d8") }
{ "_id" : ObjectId("570557d4094a4514fc1291e9"), "email": "u8@mail.com", "user_type" : "3", "grade" : "A1", "room_id" : ObjectId("580557d4094a4514fc1291d8") }
我想找到具有 grade
A2 的类型 2 用户的电子邮件 ID,以及具有相同 room_id
但 user_type
3(grade
确实室友无所谓)。所以结果数据应该是这样的:
{"email": "u2@mail.com", "roommates": [{"email": "u3@mail.com"}]}
{"email": "u4@mail.com", "roommates": [{"email": "u5@mail.com"}, {"email": "u6@mail.com"}]}
如何在 MongoDB 中执行此操作?我有 SQL 的背景,所以我正在考虑自连接,但我想还有其他方法可以做到。
是的,self-join users
合集的(concept/direction)是正确的。
$lookup
- 通过room_id
和 returnroommates
数组加入users
集合。
过滤文档$match
- 按user_type
、grade
和roommates.user_type
.$project
- 修饰输出文档。3.1。
$map
- 迭代roommates
数组和 return 数组。3.1.1。
$filter
- 在roommates
数组中使用user_type
过滤文档。
db.users.aggregate([
{
$lookup: {
from: "users",
localField: "room_id",
foreignField: "room_id",
as: "roommates"
}
},
{
$match: {
user_type: "2",
grade: "A2",
"roommates.user_type": "3"
}
},
{
$project: {
email: 1,
roommates: {
$map: {
input: {
$filter: {
input: "$roommates",
cond: {
$eq: [
"$$this.user_type",
"3"
]
}
}
},
in: {
email: "$$this.email"
}
}
}
}
}
])