mongodb - 如何使用 MongoDB 聚合 $lookup 和 $addFields 比较字段并在匹配时返回值?
问题描述
我有 2 个 MongoDB 集合,这里有 2 个模型示例:
用户集合:
{
_id: ObjectId,
available: Boolean,
province: String,
city: String,
[...]
}
距离集合:
{
_id: ObjectId,
start_province: String,
start_city: String,
end_province: String,
end_city: String,
distance: Number
}
我需要的是使用类似的查询来查找用户{available: true}
,然后使用一些聚合向每个用户文档添加一个距离字段,如果用户的省和城市之间存在匹配,则距离字段(start_province和start_city是在此堆栈之前在 JS 中定义的固定值)。
如果有匹配距离应包含距离值,否则为 0(或未定义)。
我认为我应该使用 $lookup 和/或 $addFields,但我对聚合运算符还没有足够的信心来解决这个问题。
用户结果示例:
[
{
_id: ObjectId,
available: Boolean,
province: String,
city: String,
[...],
distance: Number
},
{...}
]
谢谢你的帮助!
编辑: 按要求添加示例数据:
Users
[
{name: 'John', available: true, province: 'Rome', city: 'Tivoli'},
{name: 'Difool', available: true, province: 'Rome', city: 'Ostia'},
{name: 'Paul', available: true, province: 'Rome', city: 'Rome'},
{name: 'Andrew', available: false, province: 'Rome', city: 'Grottaferrata'}
]
Distances
[
{start_province: 'Rome', start_city: 'Rome', end_province: 'Rome', end_city: 'Ostia', distance: 5},
{start_province: 'Rome', start_city: 'Rome', end_province: 'Rome', end_city: 'Tivoli', distance: 8}
]
用户的预期结果
[
{name: 'John', available: true, province: 'Rome', city: 'Tivoli', distance: 8},
{name: 'Difool', available: true, province: 'Rome', city: 'Ostia', distance: 5},
{name: 'Paul', available: true, province: 'Rome', city: 'Rome', distance: 0}
]
过滤查询:
{ available: true }
User.province需要与Distance.end_province匹配
User.city需要与Distance.end_city匹配。
否则,距离应返回 0 或未定义。谢谢。
解决方案
询问
- 过滤以保持可用
- 如果加入
- User.province 需要与 Distance.end_province 匹配
- User.city 需要与 Distance.end_city 匹配。
- 如果未加入 => 距离=0 否则获取与第一个加入文档的距离
- 取消距离(连接结果)
*如果您有 mongodb <5 和索引,如果您可以使用 $eq 查询运算符进行第二次匹配,而不是我使用的聚合 $eq(它相同,只需删除 $expr 并使用查询 $eq)
db.users.aggregate([
{
"$match": {
"available": {
"$eq": true
}
}
},
{
"$lookup": {
"from": "distances",
"let": {
"uprovince": "$province",
"ucity": "$city"
},
"pipeline": [
{
"$match": {
"$expr": {
"$and": [
{
"$eq": [
"$$uprovince",
"$end_province"
]
},
{
"$eq": [
"$$ucity",
"$end_city"
]
}
]
}
}
}
],
"as": "distances"
}
},
{
"$set": {
"distance": {
"$cond": [
{
"$eq": [
"$distances",
[]
]
},
0,
{
"$arrayElemAt": [
"$distances.distance",
0
]
}
]
}
}
},
{
"$unset": [
"distances"
]
}
])
推荐阅读
- django - Django 应用程序,vue.js 仅在 vue 在 HTML 文件中时才有效
- node.js - express.session 在通过其域访问应用程序时不会在 iOS Safari 上设置 cookie
- java - 使用 GSON 时更改列表的输出格式
- pyspark - PySpark - 无法按另一列的值过滤行
- reactjs - 无法使用 ReactTestUtils 对 useClickAway 进行单元测试
- excel - 更改多个工作簿查询的单个数据源
- c# - 如何在 GemBox 中使用 2 MultipleBorders 选项
- amazon-web-services - 如何从 Cost Explorer 解析出多个标签?
- java - 覆盖父方法无法正常工作
- android - 当我从字符串数组更改语言时应用程序崩溃