在 MongoDB 中使用查找运算符连接多个条件
今天,我们将了解如何在 MongoDB 中使用 $lookup
运算符连接多个条件。此外,我们还将探索一些示例来演示 $group
阶段和 $unionWidth
聚合阶段的使用。
在 MongoDB 中使用 $lookup
运算符连接多个条件
如果我们有 MongoDB 3.6 或更高版本,我们可以使用 $lookup
聚合 pipeline
运算符来连接多个条件。
为此,我们有两个名为 users
和 salaries
的集合。你也可以使用以下命令创建它。
创建集合的示例代码:
> db.createCollection('users')
> db.createCollection('salaries')
在 users
集合中插入文档的示例代码:
> db.users.insertMany(
[
{
username: 'userone',
age: 30,
gender: 'Female',
city: 'Lahore',
country: 'Pakistan'
},
{
username: 'usertwo',
age: 35,
gender: 'Male',
city: 'Florida',
country: 'United States'
}
]
)
在 salaries
集合中插入文档的示例代码:
> db.salaries.insertMany(
[
{
username: 'userone',
salary: 3000
},
{
username: 'usertwo',
salary: 5000
}
]
)
users
集合的显示数据:
> db.users.find().pretty()
输出:
{
"_id" : ObjectId("628deb40c1e812eeeb311439"),
"username" : "userone",
"age" : 30,
"gender" : "Female",
"city" : "Lahore",
"country" : "Pakistan"
}
{
"_id" : ObjectId("628deb40c1e812eeeb31143a"),
"username" : "usertwo",
"age" : 35,
"gender" : "Male",
"city" : "Florida",
"country" : "United States"
}
salaries
集合的显示数据:
> db.salaries.find().pretty()
输出:
{
"_id" : ObjectId("628deb07c1e812eeeb311437"),
"username" : "userone",
"salary" : 3000
}
{
"_id" : ObjectId("628deb07c1e812eeeb311438"),
"username" : "usertwo",
"salary" : 5000
}
创建集合并插入文档后,我们可以探索各种场景来加入多个条件。让我们从 $lookup
开始。
使用 $lookup
聚合 pipeline
运算符
示例代码:
> db.users.aggregate([
{
$lookup: {
from: 'salaries',
let: {
user_name: '$username',
user_salary: 3000
},
pipeline: [{
$match: {
$expr: {
$and: [
{ $eq: ['$username', '$$user_name'] },
{ $gte: ['$salary','$$user_salary'] }
]
}
}
}],
as: 'usersalary'
}
}
]).pretty()
输出:
{
"_id" : ObjectId("628deb40c1e812eeeb311439"),
"username" : "userone",
"age" : 30,
"gender" : "Female",
"city" : "Lahore",
"country" : "Pakistan",
"usersalary" : [
{
"_id" : ObjectId("628deb07c1e812eeeb311437"),
"username" : "userone",
"salary" : 3000
}
]
}
{
"_id" : ObjectId("628deb40c1e812eeeb31143a"),
"username" : "usertwo",
"age" : 35,
"gender" : "Male",
"city" : "Florida",
"country" : "United States",
"usersalary" : [
{
"_id" : ObjectId("628deb07c1e812eeeb311438"),
"username" : "usertwo",
"salary" : 5000
}
]
}
在这里,我们得到满足两个条件的文档。
我们只得到满足这两个条件的文件。你可能已经注意到 usersalary
是一个元素数组,其中每个元素都是 salaries
集合的文档。
我们可以使用 $unwind
、$addFields
和 $project
从两个集合(users
和 salaries
)中获取特定字段并形成一个文档,如下例所示。
示例代码:
> db.users.aggregate([
{
$lookup: {
from: 'salaries',
let: {
user_name: '$username',
user_salary: 3000
},
pipeline: [{
$match: {
$expr: {
$and: [
{ $eq: ['$username', '$$user_name'] },
{ $gte: ['$salary','$$user_salary'] }
]
}
}
}],
as: 'usersalary'
}
},
{
$unwind:'$usersalary'
},
{
$addFields: {
salary: '$usersalary.salary'
}
},
{
$project: {
username: 1,
salary: 1
}
}
]).pretty()
输出:
{
"_id" : ObjectId("628deb40c1e812eeeb311439"),
"username" : "userone",
"salary" : 3000
}
{
"_id" : ObjectId("628deb40c1e812eeeb31143a"),
"username" : "usertwo",
"salary" : 5000
}
使用 $unwind
运算符的目的是为每个具有相同名称的元素解构一个数组字段,从输入文档到输出一个文档。
如果数组中只有一个元素,则 $unwind
阶段运算符将对象展平,即元素本身。 $addFields
将对象或数组中的 salary
字段连接到文档的根级别。
在了解上面给出的示例中的用法之前,让我们先关注使用 $project
过滤器阶段的原因。如果我们不使用 $project
,我们将获得文档根级别的 salary
字段和 usersalary
对象,这是不必要的。
这是我们使用 $project
过滤阶段并指定输出中应包含哪些字段的地方。
如果项目要求限制使用 $unwind
、$addFields
、$project
,我们可以使用下面给出的替代解决方案。
示例代码:
> db.users.aggregate([
{
$lookup: {
from: 'salaries',
let: {
user_name: '$username',
user_salary: 3000
},
pipeline: [{
$match: {
$expr: {
$and: [
{ $eq: ['$username', '$$user_name'] },
{ $gte: ['$salary','$$user_salary'] }
]
}
}
}],
as: 'usersalary'
}
},
{
$replaceRoot: {
newRoot: {
$mergeObjects:[
{
$arrayElemAt: [
"$usersalary", 0
]
},
{
salary: "$$ROOT.salary"
}
]
}
}
}
]
).pretty()
输出:
{
"_id" : ObjectId("628deb07c1e812eeeb311437"),
"username" : "userone",
"salary" : 3000
}
{
"_id" : ObjectId("628deb07c1e812eeeb311438"),
"username" : "usertwo",
"salary" : 5000
}
我们使用 let
字段(可选)将字段的值分配给变量。我们在 pipeline
阶段访问这些变量,我们指定 pipeline
在不同的集合上执行。
请注意,我们还使用 $match
阶段来利用名为 $expr
的评估查询运算符,它比较字段的值。
此外,$replaceRoot
是 pipeline
中的最后一个聚合 pipeline
阶段,我们使用 $mergeObjects
运算符将 $lookup
输出与 $$ROOT
文档的部分合并。
我们只使用了 $and
运算符来连接条件。你也可以使用 $or
或两个运算符。
创建新集合并使用 $group
聚合阶段加入多个条件
示例代码:
> db.users_salaries.insertMany(
db.users.find({}, {"_id": 0})
.toArray()
.concat(db.salaries.find({}, {"_id": 0}).toArray())
)
db.users_salaries.aggregate([
{ "$group": {
"_id": { "username": "$username" },
"salary": { "$push": "$salary" }
}}
])
输出:
{ "_id" : { "username" : "userone" }, "salary" : [ 3000 ] }
{ "_id" : { "username" : "usertwo" }, "salary" : [ 5000 ] }
对于这个代码示例,我们创建一个名为 users_salaries
的新集合,合并两个名为 users
和 salaries
的集合,然后将这些文档插入到新创建的集合中。然后,按用户名
分组以获得所需的输出。
我们也可以在不创建新集合的情况下获得相同的输出(如上所示)。为此,我们使用 $unionWith
聚合阶段,它为两个集合执行联合。
示例代码:
> db.users.aggregate([
{ $set: { username: "$username" } },
{ $unionWith: {
coll: "salaries",
pipeline: [{ $set: { salary: "$salary" } }]
}},
{ $group: {
_id: { username: "$username"},
"salary": { "$push": "$salary" }
}}
])
输出:
{ "_id" : { "username" : "userone" }, "salary" : [ 3000 ] }
{ "_id" : { "username" : "usertwo" }, "salary" : [ 5000 ] }
相关文章
在 MongoDB Shell 中列出所有数据库
发布时间:2023/05/11 浏览次数:180 分类:MongoDB
-
交互式 Mongo Shell 提供了多个用于获取数据的选项。 本文介绍了在 Mongo Shell 中列出数据库的几种不同方法。
MongoDB 中检查字段包含的字符串
发布时间:2023/05/11 浏览次数:1024 分类:MongoDB
-
这篇文章解决了如何在 MongoDB 中使用正则表达式来确定字段是否包含字符串。在 MongoDB 中使用正则表达式 正则表达式 (regex) 是定义搜索模式的文本字符串。
在 MongoDB 中 upsert 更新插入
发布时间:2023/05/11 浏览次数:214 分类:MongoDB
-
在 MongoDB 中,upsert 结合了更新和插入命令。 它可以在 update() 和 findAndModify() 操作中使用。MongoDB 中的 upsert 查询 upsert 采用单个布尔参数。
如何卸载 MongoDB
发布时间:2023/05/11 浏览次数:745 分类:MongoDB
-
要从您的计算机中卸载 MongoDB,您必须先删除 MongoDB 服务、数据库和日志文件。使用这篇 MongoDB 文章,您将能够从 Ubuntu Linux、Mac 和 Windows 卸载 MongoDB。 请务必保留数据备份,因为一旦卸载,便
在 MongoDB 中存储日期和时间
发布时间:2023/05/11 浏览次数:762 分类:MongoDB
-
本 MongoDB 教程解释了 Date() 对象是什么以及如何使用 Date() 方法对集合进行排序。 这也将帮助您找到在 MongoDB 中显示和存储日期/时间的最佳方法。
MongoDB 按 ID 查找
发布时间:2023/05/11 浏览次数:1856 分类:MongoDB
-
MongoDB 中的 find by Id() 函数用于获取与用户提供的 id 相匹配的文档。 如果找不到与指定 ID 匹配的文档,则返回空值。
检查 MongoDB 服务器是否正在运行
发布时间:2023/05/11 浏览次数:247 分类:MongoDB
-
这篇 MongoDB 教程将告诉您如何检查是否安装了 MongoDB 以及安装的 MongoDB 服务器的版本。 它在 Windows、UBUNTU 和 MAC 等不同的操作系统中实现。
MongoDB 中的分页
发布时间:2023/05/11 浏览次数:174 分类:MongoDB
-
这篇文章将介绍什么是 MongoDB 中的分页。 为什么在 MongoDB 中需要分页以及在 MongoDB 中完成分页的不同方法或方式是什么。
MongoDB 从查询开始
发布时间:2023/05/11 浏览次数:186 分类:MongoDB
-
在这篇 MongoDB 文章中,用户将学习如何使用 $regex 进行开始查询。 它为查询中的模式匹配字符串提供正则表达式功能。