使用 MongoDB 将两个集合合并为一个集合
今天,我们将使用 $lookup
聚合阶段、pipeline
和 $unwind
运算符、$project
过滤阶段和 MongoDB Compass 将两个集合合并为一个集合。
使用 MongoDB 将两个集合合并为一个集合
我们有不同的方法可以使用 MongoDB 将两个集合组合成一个集合。其中一些在下面给出,我们将在本教程中介绍。
对于上述所有场景,我们必须有一个包含两个集合(与 MySQL 中的表相同)的数据库,其中填充了文档(与 MySQL 中的记录相同)。我们使用以下查询完成了这项工作;你也可以这样做。
创建两个名为 usersInformation
和 userAddress
的集合,它们位于 users
数据库中。此外,使用以下文档填充它们。
创建数据库和集合:
> use users
> db.createCollection('userInformation')
> db.createCollection('userAddress')
用两个文档填充 userInformation
集合:
> db.userInformation.insertMany(
[
{
fullname: 'Mehvish Ashiq',
age: 30,
gender: 'Female',
nationality: 'Pakistani'
},
{
fullname: 'James Daniel',
age: 45,
sex: 'male',
nationality: 'Canadian'
}
]
)
用两个文档填充 userAddress
集合:
> db.userAddress.insertMany(
[
{
fullname: 'Mehvish Ashiq',
block_number: 22,
street: 'Johar Town Street',
city: 'Lahore'
},
{
fullname: 'James Daniel',
block_number: 30,
street: 'Saint-Denis Street',
city: 'Montreal'
}
]
)
我们使用 insertMany()
函数插入多个文档。现在,我们可以使用下面的命令来查看两个集合的数据。
在下面的代码片段中,pretty()
方法显示了干净且格式化的输出,这在 shell 上很容易理解。
显示来自 userInformation
的文档:
> db.userInformation.find().pretty()
输出:
{
"_id" : ObjectId("628bc4a45c544feccff5a566"),
"fullname" : "Mehvish Ashiq",
"age" : 30,
"gender" : "Female",
"nationality" : "Pakistani"
}
{
"_id" : ObjectId("628bc4a45c544feccff5a567"),
"fullname" : "James Daniel",
"age" : 45,
"sex" : "male",
"nationality" : "Canadian"
}
显示来自 userAddress
的文档:
> db.userAddress.find().pretty()
输出:
{
"_id" : ObjectId("628bc4ae5c544feccff5a568"),
"fullname" : "Mehvish Ashiq",
"block_number" : 22,
"street" : "Johar Town Street",
"city" : "Lahore"
}
{
"_id" : ObjectId("628bc4ae5c544feccff5a569"),
"fullname" : "James Daniel",
"block_number" : 30,
"street" : "Saint-Denis Street",
"city" : "Montreal"
}
两个集合必须在同一个数据库中才能使用 $lookup
聚合阶段。一旦两个集合都准备好了,我们可以根据我们的场景使用各种查询来连接两个集合的数据。
使用 $lookup
聚合阶段将两个集合合二为一
示例代码:
> db.userInformation.aggregate([
{ $lookup:
{
from: 'userAddress',
localField: 'fullname',
foreignField: 'fullname',
as: 'address'
}
}
]).pretty();
输出:
{
"_id" : ObjectId("628bc4a45c544feccff5a566"),
"fullname" : "Mehvish Ashiq",
"age" : 30,
"gender" : "Female",
"nationality" : "Pakistani",
"address" : [
{
"_id" : ObjectId("628bc4ae5c544feccff5a568"),
"fullname" : "Mehvish Ashiq",
"block_number" : 22,
"street" : "Johar Town Street",
"city" : "Lahore"
}
]
}
{
"_id" : ObjectId("628bc4a45c544feccff5a567"),
"fullname" : "James Daniel",
"age" : 45,
"sex" : "male",
"nationality" : "Canadian",
"address" : [
{
"_id" : ObjectId("628bc4ae5c544feccff5a569"),
"fullname" : "James Daniel",
"block_number" : 30,
"street" : "Saint-Denis Street",
"city" : "Montreal"
}
]
}
在 MongoDB 数据库中,$lookup
聚合阶段执行与其他集合的左外连接,并从连接的文档中过滤信息(数据)。例如,我们使用查询来获取所有用户的信息及其地址。
$lookup
函数接受四个字段。首先是 from
字段,我们在其中指定应该与另一个集合连接的集合。
第二个是 localField
字段。它是 from
字段中指定的集合的输入文档的属性(字段)之一。
它用于对集合文档中的 localField
与 foreignField
执行匹配。
类似地,名为 foreignField
的第三个字段也对集合文档中的 foreignField
与 localField
执行相等匹配。
我们为第四个字段 as
写下新数组的名称。有关 $lookup
聚合阶段的说明,请参见以下说明。
使用 pipeline
运算符根据指定条件将两个集合合并为一个
示例代码:
> db.userInformation.aggregate([{
$lookup:{
from: 'userAddress',
let: {full_name: '$fullname'},
pipeline: [{
$match: {
$expr: {
$eq: ['$fullname', '$$full_name']
}
}
}],
as: 'addressInfo'
}
}]).pretty()
输出:
{
"_id" : ObjectId("628bc4a45c544feccff5a566"),
"fullname" : "Mehvish Ashiq",
"age" : 30,
"gender" : "Female",
"nationality" : "Pakistani",
"addressInfo" : [
{
"_id" : ObjectId("628bc4ae5c544feccff5a568"),
"fullname" : "Mehvish Ashiq",
"block_number" : 22,
"street" : "Johar Town Street",
"city" : "Lahore"
}
]
}
{
"_id" : ObjectId("628bc4a45c544feccff5a567"),
"fullname" : "James Daniel",
"age" : 45,
"sex" : "male",
"nationality" : "Canadian",
"addressInfo" : [
{
"_id" : ObjectId("628bc4ae5c544feccff5a569"),
"fullname" : "James Daniel",
"block_number" : 30,
"street" : "Saint-Denis Street",
"city" : "Montreal"
}
]
}
当我们想要基于特定条件连接两个集合时,我们可以使用带有 $lookup
的 pipeline
运算符(就像我们在 MySQL 中使用 WHERE
子句一样)。
例如,我们正在加入来自 userAddress
的 fullname
等于 userInformation
中的 fullname
的集合。
在附加到结果文档之前使用 $unwind
运算符来平面数组
示例代码:
> db.userInformation.aggregate([
{ $lookup:
{
from: 'userAddress',
localField: 'fullname',
foreignField: 'fullname',
as: 'address'
}
},
{
$unwind: '$address'
}
]).pretty();
输出:
{
"_id" : ObjectId("628bc4a45c544feccff5a566"),
"fullname" : "Mehvish Ashiq",
"age" : 30,
"gender" : "Female",
"nationality" : "Pakistani",
"address" : {
"_id" : ObjectId("628bc4ae5c544feccff5a568"),
"fullname" : "Mehvish Ashiq",
"block_number" : 22,
"street" : "Johar Town Street",
"city" : "Lahore"
}
}
{
"_id" : ObjectId("628bc4a45c544feccff5a567"),
"fullname" : "James Daniel",
"age" : 45,
"sex" : "male",
"nationality" : "Canadian",
"address" : {
"_id" : ObjectId("628bc4ae5c544feccff5a569"),
"fullname" : "James Daniel",
"block_number" : 30,
"street" : "Saint-Denis Street",
"city" : "Montreal"
}
}
$unwind
运算符什么也不做,只是在将数组附加到结果文档之前将其展平。 $unwind
运算符的根本区别在于它将具有单个元素的数组转换为扁平对象,即元素本身。
请记住,此元素的名称不会更改。当元素为数组形式时,它与以前相同。
使用和不使用 $unwind
运算符执行上述查询并观察 address
字段。
在聚合查询中使用 $project
过滤器阶段将两个集合合二为一
在使用 $project
加入集合之前,让我们了解它的重要性。例如,如果我们不想将名为 userAddress
的整个集合与 userInformation
连接起来,我们只希望连接 city
和 street
字段。
在这种情况下,我们需要使用 $addFields
阶段。我们使用此阶段将数组/对象中的任何字段或多个字段加入/分配到文档的根级别。
因此,我们执行以下查询以从 userAddress
集合中检索 city
和 street
。
示例代码:
> db.userInformation.aggregate([
{ $lookup:
{
from: 'userAddress',
localField: 'fullname',
foreignField: 'fullname',
as: 'address'
}
},
{
$unwind: '$address'
},
{
$addFields: {
street: '$address.street',
city: '$address.city'
}
}
]).pretty();
输出:
{
"_id" : ObjectId("628bc4a45c544feccff5a566"),
"fullname" : "Mehvish Ashiq",
"age" : 30,
"gender" : "Female",
"nationality" : "Pakistani",
"address" : {
"_id" : ObjectId("628bc4ae5c544feccff5a568"),
"fullname" : "Mehvish Ashiq",
"block_number" : 22,
"street" : "Johar Town Street",
"city" : "Lahore"
},
"street" : "Johar Town Street",
"city" : "Lahore"
}
{
"_id" : ObjectId("628bc4a45c544feccff5a567"),
"fullname" : "James Daniel",
"age" : 45,
"sex" : "male",
"nationality" : "Canadian",
"address" : {
"_id" : ObjectId("628bc4ae5c544feccff5a569"),
"fullname" : "James Daniel",
"block_number" : 30,
"street" : "Saint-Denis Street",
"city" : "Montreal"
},
"street" : "Saint-Denis Street",
"city" : "Montreal"
}
仔细关注上面给出的输出。我们得到了街道
和城市
吗?是的,我们在文档的根级别获得了 street
和 city
,但也有我们现在不需要的 address
对象。
这就是 $project
过滤阶段的用武之地。它指定我们应该在结果文档中包含哪些字段。
请参阅以下查询以获得更好的理解。
示例代码:
> db.userInformation.aggregate([
{ $lookup:
{
from: 'userAddress',
localField: 'fullname',
foreignField: 'fullname',
as: 'address'
}
},
{
$unwind: '$address'
},
{
$addFields: {
street: '$address.street',
city: '$address.city'
}
},
{
$project: {
fullname: 1,
age: 1,
gender: 1,
street: 1,
city: 1
}
}
]).pretty();
输出:
{
"_id" : ObjectId("628bc4a45c544feccff5a566"),
"fullname" : "Mehvish Ashiq",
"age" : 30,
"gender" : "Female",
"street" : "Johar Town Street",
"city" : "Lahore"
}
{
"_id" : ObjectId("628bc4a45c544feccff5a567"),
"fullname" : "James Daniel",
"age" : 45,
"street" : "Saint-Denis Street",
"city" : "Montreal"
}
如你所见,我们现在没有 address
对象,但它的两个字段(street
和 city
)被分配给文档的根级别。
使用 Compass 连接两个集合(MongoDB 的图形界面)
使用图形界面进行聚合很容易。我们只需要在 $lookup
聚合阶段执行以下步骤。
相关文章
比较 MongoDB 中的字段
发布时间:2023/04/21 浏览次数:51 分类:MongoDB
-
在本文中,我们将了解如何比较 MongoDB 中的两个字段。 此外,我们将看到一个相关的示例和解释,以使主题更容易理解。
清除或删除 MongoDB 中的集合
发布时间:2023/04/21 浏览次数:147 分类:MongoDB
-
本篇文章将告诉大家如何删除 MongoDB 数据库中的集合以及删除 MongoDB 中的集合的不同方法。
向 MongoDB 集合中的每个文档添加新字段
发布时间:2023/04/21 浏览次数:107 分类:MongoDB
-
您将在这篇文章中了解 $set 和 $setOnInsert 操作。 此外,利用这两个运算符,快速描述了向 MongoDB 中的集合添加字段的挑战。
MongoDB 截断集合
发布时间:2023/04/21 浏览次数:178 分类:MongoDB
-
可以根据需要选择两个选项之一来截断下面的集合。 在今天的文章中,我们将学习如何在 MongoDB 中截断集合。
删除 MongoDB 中的重复项
发布时间:2023/04/21 浏览次数:151 分类:MongoDB
-
在本文中,我们将了解如何删除 MongoDB 中的重复条目,并且我们还将看到一个带有适当解释的示例,以使主题更容易理解。
使用 NodeJS 检查 MongoDB 中是否存在集合
发布时间:2023/04/21 浏览次数:194 分类:MongoDB
-
在本文中,我们将检查 MongoDB 数据库中是否存在一个集合,并且我们还将查看与主题相关的示例,以使主题更容易理解。 为此,我们将使用 Node.js。
MongoDB 中的唯一索引
发布时间:2023/04/21 浏览次数:144 分类:MongoDB
-
在这篇教学文章中,您将了解唯一索引、它们是什么以及如何在 MongoDB 中使索引唯一。 此外,还简要详细地解释了使用户的电子邮件在 MongoDB 中唯一。
在 MongoDB 中创建索引
发布时间:2023/04/21 浏览次数:104 分类:MongoDB
-
索引有助于有效解决查询。 如果没有索引,MongoDB 必须遍历集合中的每个文档才能找到与查询匹配的文档。因此,在今天的文章中,我们将学习如何在 MongoDB 中创建索引。
MongoDB 中的稀疏索引
发布时间:2023/04/21 浏览次数:142 分类:MongoDB
-
在本文中,我们将讨论 MongoDB 中的稀疏索引。 此外,我们将提供一个相关示例并进行解释,以使该主题更容易理解。