1. 什么是连表查询
在数据库中,连表查询常常用于从多个表中按特定条件检索的过程,该过程便是对多个表的统一查询(即通过联结)。
举例来说,公司员工表和部门表通常需要联结在一起,以便从员工表中查询特定部门的员工详细信息。在执行这个查询之前,“部门表”和“员工表”需要预先联结在一起。
2. 连表查询的优缺点
2.1 优点
联结两个或多个表通常可以获得与在单个表中执行查询相比更大的结果集。 这种查询通常比单个表的查询更有用。
此外,多个表的数据通常彼此相关,因此联结表可以更好地利用这些关系。 联结表还可以使列排序和筛选更容易。
2.2 缺点
尽管联结表可以创造有关数据的更丰富的查询,但此类查询往往是比单个表查询更复杂和更耗时。 如果您的查询涉及多个大型表,这可能会对数据库的性能造成负面影响。
3. 如何进行连表查询
在MongoDB中,要在两个或多个表之间进行联接,你可以使用 $lookup
操作符。这个操作符实现了关系数据库系统中类似于 JOIN - ON和WHERE子句的操作。关于操作符中更多的内容可以参考官方文档。
下面简要介绍在MongoDB中如何进行联结:
3.1 创建两个表和文档
假设我们有两个表:employees和departments。它们各自可以包含与员工和部门有关的信息。
接下来我们需要为这两个表添加一些示例文档,用于后续的查询演示。
db.employees.insertMany([
{ name: "Alice", departmentId: 1 },
{ name: "Bob", departmentId: 1 },
{ name: "Charlie", departmentId: 2 },
{ name: "Dave", departmentId: 3 },
{ name: "Eve", departmentId: null }
])
db.departments.insertMany([
{ id: 1, name: "HR" },
{ id: 2, name: "Marketing" },
{ id: 3, name: "Engineering" },
{ id: 4, name: "Sales" }
])
以上两段执行完成后,我们就可以在“employees”表中查看它们的信息了。
db.employees.find()
结果如下:
{
"_id": ObjectId("5fdcef4634c9be0beaca7c65"),
"name": "Alice",
"departmentId": 1
},
{
"_id": ObjectId("5fdcef4634c9be0beaca7c66"),
"name": "Bob",
"departmentId": 1
},
{
"_id": ObjectId("5fdcef4634c9be0beaca7c67"),
"name": "Charlie",
"departmentId": 2
},
{
"_id": ObjectId("5fdcef4634c9be0beaca7c68"),
"name": "Dave",
"departmentId": 3
},
{
"_id": ObjectId("5fdcef4634c9be0beaca7c69"),
"name": "Eve",
"departmentId": null
}
同样,我们也能在“departments”表中查看到它们的信息:
db.departments.find()
结果如下:
{
"_id": ObjectId("5fdcef4634c9be0beaca7c6a"),
"id": 1,
"name": "HR"
},
{
"_id": ObjectId("5fdcef4634c9be0beaca7c6b"),
"id": 2,
"name": "Marketing"
},
{
"_id": ObjectId("5fdcef4634c9be0beaca7c6c"),
"id": 3,
"name": "Engineering"
},
{
"_id": ObjectId("5fdcef4634c9be0beaca7c6d"),
"id": 4,
"name": "Sales"
}
3.2 连接两个表
接下来,我们将使用 $lookup
中的参数来实现“employees”表和“departments”表的连接。在此过程中,两个表之间共享的“departmentId”将用作匹配项。
db.employees.aggregate([
{
$lookup:
{
from: "departments",
localField: "departmentId",
foreignField: "id",
as: "department"
}
}
])
上述代码实现了“employees”和“departments”之间的联接。关于参数“from”、“localField”、“foreignField”和“as”的含义具体可以查看官方文档。
查询结果如下:
[
{
"_id": ObjectId("5fdcef4634c9be0beaca7c65"),
"name": "Alice",
"departmentId": 1,
"department": [
{
"_id": ObjectId("5fdcef4634c9be0beaca7c6a"),
"id": 1,
"name": "HR"
}
]
},
{
"_id": ObjectId("5fdcef4634c9be0beaca7c66"),
"name": "Bob",
"departmentId": 1,
"department": [
{
"_id": ObjectId("5fdcef4634c9be0beaca7c6a"),
"id": 1,
"name": "HR"
}
]
},
{
"_id": ObjectId("5fdcef4634c9be0beaca7c67"),
"name": "Charlie",
"departmentId": 2,
"department": [
{
"_id": ObjectId("5fdcef4634c9be0beaca7c6b"),
"id": 2,
"name": "Marketing"
}
]
},
{
"_id": ObjectId("5fdcef4634c9be0beaca7c68"),
"name": "Dave",
"departmentId": 3,
"department": [
{
"_id": ObjectId("5fdcef4634c9be0beaca7c6c"),
"id": 3,
"name": "Engineering"
}
]
},
{
"_id": ObjectId("5fdcef4634c9be0beaca7c69"),
"name": "Eve",
"departmentId": null,
"department": [ ]
}
]
这个结果返回了两个表的信息,其中包含部门信息。
4. 总结
在MongoDB中,通过联结两个表可以增强对数据的查询功能。在开始联结之前,首先需要确保库中存在需要联结的表和文档。然后,使用 $lookup
参数关联两个表。
虽然联接表可能会增加查询的复杂性和开销,但如果能够更好地组织数据,它们最终可能会对系统的性能产生积极的影响。