mongodb - 有条件的左连接
mongodb - left join with conditions
我正在尝试对这两个 collections 进行左反连接。
我希望部门等于 'IT' 的所有用户不在 endAt 时间 > 175 的会议中。作为创建者或接收者。
所以基本上谁在上次 xxx 时间没有参加会议。
基于以下 collections:
John 将被检索到,因为他属于 IT 部门,并且在“175”之后不是接收者或创建者。
Jane 在 175 之后有一个 endAt 时间并且在 IT 中所以不会被检索
比尔是财务部门的一部分,所以即使他不是财务部门也没关系
Bob 在 175 之后有一个 endAt 时间并且在 IT 中所以不会被检索
玛丽在 IT 部门,没有参加任何会议,所以她被找回了。
用户Collection:
[
{
_id: ObjectId("1"),
name: "john",
department: 'IT'
},
{
_id: ObjectId("2"),
name: "jane",
department: 'IT'
},
{
_id: ObjectId("3"),
name: "bill",
department: 'finance'
},
{
_id: ObjectId("4"),
name: "Bob",
department: 'IT'
},
{
_id: ObjectId("5"),
name: "Mary",
department: 'IT'
}
]
会议Collection:
[
{
_id: ObjectId("a"),
endedAt: 100,
creator_id: ObjectId("1"),
receiver_id: ObjectId("2")
},
{
_id: ObjectId("b"),
endedAt: 150,
creator_id: ObjectId("1"),
receiver_id: ObjectId("3")
},
{
_id: ObjectId("c"),
endedAt: 200,
creator_id: ObjectId("4"),
receiver_id: ObjectId("2")
},
{
_id: ObjectId("d"),
endedAt: 250,
creator_id: ObjectId("2"),
receiver_id:
}
]
输出:
[
{
_id: ObjectId("1"),
name: "john",
department: 'IT'
},
{
_id: ObjectId("5"),
name: "Mary",
department: 'IT'
}
]
我的做法:
db.users.aggregate([
{
$match:
{
type: 'IT'
}
},
{
$lookup:
{
from: "meetings",
let:
{
userid: "$_id",
},
pipeline: [
{ $match:
{ $expr:
{
$and:[
{
$or: [
{ $eq: ["$receiver_id", "$$userid"] },
{ $eq: ["$creator_id", "$$userid"] },
]
},
{ $gt: ["$endAt", 175] }
]
}
}
}
],
as: "result"
}
},
{
$unwind:
{
path: "$result",
preserveNullAndEmptyArrays: true
}
},
{
$match:
{
result: {$exists:false}
}
}
])
汇总
db.users.aggregate([
{
"$match": {
department: "IT"
}
},
{
"$lookup": {
"from": "meeting",
"localField": "_id",
"foreignField": "creator_id",
"as": "meeting_creator"
}
},
{
"$lookup": {
"from": "meeting",
"localField": "_id",
"foreignField": "receiver_id",
"as": "meeting_receiver"
}
},
{
"$match": {
"$and": [
{
"meeting_creator.endedAt": {
"$not": {
"$gt": 175
}
}
},
{
"meeting_receiver.endedAt": {
"$not": {
"$gt": 175
}
}
}
]
}
},
{
"$project": {
_id: 1,
name: 1,
department: 1
}
}
])
数据
db={
"users": [
{
_id: "1",
name: "john",
department: "IT"
},
{
_id: "2",
name: "jane",
department: "IT"
},
{
_id: "3",
name: "bill",
department: "finance"
},
{
_id: "4",
name: "Bob",
department: "IT"
},
{
_id: "5",
name: "Mary",
department: "IT"
}
],
"meeting": [
{
_id: "a",
endedAt: 100,
creator_id: "1",
receiver_id: "2"
},
{
_id: "b",
endedAt: 150,
creator_id: "1",
receiver_id: "3"
},
{
_id: "c",
endedAt: 200,
creator_id: "4",
receiver_id: "2"
},
{
_id: "d",
endedAt: 250,
creator_id: "2",
receiver_id: ""
}
]
}
结果
[
{
"_id": "1",
"department": "IT",
"name": "john"
},
{
"_id": "5",
"department": "IT",
"name": "Mary"
}
]
查询
- 匹配“IT”
- 加入如果 >175 AND(userid 在任何 2 (creator/receiver))
*它的查找管道,因为 multiple join creteria
- 拒绝加入的
db.users.aggregate([
{
"$match": {
"department": {
"$eq": "IT"
}
}
},
{
"$lookup": {
"from": "meetings",
"let": {
"userid": "$_id"
},
"pipeline": [
{
"$match": {
"$expr": {
"$and": [
{
"$gt": [
"$endedAt",
175
]
},
{
"$or": [
{
"$eq": [
"$$userid",
"$creator_id"
]
},
{
"$eq": [
"$$userid",
"$receiver_id"
]
}
]
}
]
}
}
},
{
"$project": {
"_id": 1
}
}
],
"as": "meetings"
}
},
{
"$match": {
"$expr": {
"$eq": [
"$meetings",
[]
]
}
}
},
{
"$unset": [
"meetings"
]
}
])
这是我想出的最终有效的解决方案,有人知道什么是最有效的吗?
db.users.aggregate([
{
$match:
{
type: 'IT'
}
},
{
$lookup:
{
from: "meetings",
let:
{
userid: "$_id",
},
pipeline: [
{ $match:
{ $expr:
{
$and:[
{
$or: [
{ $eq: ["$receiver_id", "$$userid"] },
{ $eq: ["$creator_id", "$$userid"] },
]
},
{ $gt: ["$endAt", 175] }
]
}
}
}
],
as: "result"
}
},
{
$unwind:
{
path: "$result",
preserveNullAndEmptyArrays: true
}
},
{
$match:
{
result: {$exists:false}
}
}
])
我正在尝试对这两个 collections 进行左反连接。
我希望部门等于 'IT' 的所有用户不在 endAt 时间 > 175 的会议中。作为创建者或接收者。 所以基本上谁在上次 xxx 时间没有参加会议。
基于以下 collections: John 将被检索到,因为他属于 IT 部门,并且在“175”之后不是接收者或创建者。 Jane 在 175 之后有一个 endAt 时间并且在 IT 中所以不会被检索 比尔是财务部门的一部分,所以即使他不是财务部门也没关系 Bob 在 175 之后有一个 endAt 时间并且在 IT 中所以不会被检索 玛丽在 IT 部门,没有参加任何会议,所以她被找回了。
用户Collection:
[
{
_id: ObjectId("1"),
name: "john",
department: 'IT'
},
{
_id: ObjectId("2"),
name: "jane",
department: 'IT'
},
{
_id: ObjectId("3"),
name: "bill",
department: 'finance'
},
{
_id: ObjectId("4"),
name: "Bob",
department: 'IT'
},
{
_id: ObjectId("5"),
name: "Mary",
department: 'IT'
}
]
会议Collection:
[
{
_id: ObjectId("a"),
endedAt: 100,
creator_id: ObjectId("1"),
receiver_id: ObjectId("2")
},
{
_id: ObjectId("b"),
endedAt: 150,
creator_id: ObjectId("1"),
receiver_id: ObjectId("3")
},
{
_id: ObjectId("c"),
endedAt: 200,
creator_id: ObjectId("4"),
receiver_id: ObjectId("2")
},
{
_id: ObjectId("d"),
endedAt: 250,
creator_id: ObjectId("2"),
receiver_id:
}
]
输出:
[
{
_id: ObjectId("1"),
name: "john",
department: 'IT'
},
{
_id: ObjectId("5"),
name: "Mary",
department: 'IT'
}
]
我的做法:
db.users.aggregate([
{
$match:
{
type: 'IT'
}
},
{
$lookup:
{
from: "meetings",
let:
{
userid: "$_id",
},
pipeline: [
{ $match:
{ $expr:
{
$and:[
{
$or: [
{ $eq: ["$receiver_id", "$$userid"] },
{ $eq: ["$creator_id", "$$userid"] },
]
},
{ $gt: ["$endAt", 175] }
]
}
}
}
],
as: "result"
}
},
{
$unwind:
{
path: "$result",
preserveNullAndEmptyArrays: true
}
},
{
$match:
{
result: {$exists:false}
}
}
])
汇总
db.users.aggregate([
{
"$match": {
department: "IT"
}
},
{
"$lookup": {
"from": "meeting",
"localField": "_id",
"foreignField": "creator_id",
"as": "meeting_creator"
}
},
{
"$lookup": {
"from": "meeting",
"localField": "_id",
"foreignField": "receiver_id",
"as": "meeting_receiver"
}
},
{
"$match": {
"$and": [
{
"meeting_creator.endedAt": {
"$not": {
"$gt": 175
}
}
},
{
"meeting_receiver.endedAt": {
"$not": {
"$gt": 175
}
}
}
]
}
},
{
"$project": {
_id: 1,
name: 1,
department: 1
}
}
])
数据
db={
"users": [
{
_id: "1",
name: "john",
department: "IT"
},
{
_id: "2",
name: "jane",
department: "IT"
},
{
_id: "3",
name: "bill",
department: "finance"
},
{
_id: "4",
name: "Bob",
department: "IT"
},
{
_id: "5",
name: "Mary",
department: "IT"
}
],
"meeting": [
{
_id: "a",
endedAt: 100,
creator_id: "1",
receiver_id: "2"
},
{
_id: "b",
endedAt: 150,
creator_id: "1",
receiver_id: "3"
},
{
_id: "c",
endedAt: 200,
creator_id: "4",
receiver_id: "2"
},
{
_id: "d",
endedAt: 250,
creator_id: "2",
receiver_id: ""
}
]
}
结果
[
{
"_id": "1",
"department": "IT",
"name": "john"
},
{
"_id": "5",
"department": "IT",
"name": "Mary"
}
]
查询
- 匹配“IT”
- 加入如果 >175 AND(userid 在任何 2 (creator/receiver))
*它的查找管道,因为 multiple join creteria - 拒绝加入的
db.users.aggregate([
{
"$match": {
"department": {
"$eq": "IT"
}
}
},
{
"$lookup": {
"from": "meetings",
"let": {
"userid": "$_id"
},
"pipeline": [
{
"$match": {
"$expr": {
"$and": [
{
"$gt": [
"$endedAt",
175
]
},
{
"$or": [
{
"$eq": [
"$$userid",
"$creator_id"
]
},
{
"$eq": [
"$$userid",
"$receiver_id"
]
}
]
}
]
}
}
},
{
"$project": {
"_id": 1
}
}
],
"as": "meetings"
}
},
{
"$match": {
"$expr": {
"$eq": [
"$meetings",
[]
]
}
}
},
{
"$unset": [
"meetings"
]
}
])
这是我想出的最终有效的解决方案,有人知道什么是最有效的吗?
db.users.aggregate([
{
$match:
{
type: 'IT'
}
},
{
$lookup:
{
from: "meetings",
let:
{
userid: "$_id",
},
pipeline: [
{ $match:
{ $expr:
{
$and:[
{
$or: [
{ $eq: ["$receiver_id", "$$userid"] },
{ $eq: ["$creator_id", "$$userid"] },
]
},
{ $gt: ["$endAt", 175] }
]
}
}
}
],
as: "result"
}
},
{
$unwind:
{
path: "$result",
preserveNullAndEmptyArrays: true
}
},
{
$match:
{
result: {$exists:false}
}
}
])