Mongodb $存在于 mongodb 中的 $expr 中
Mongodb $exists inside $expr in mongodb
我想在加入时添加多个条件。加入满足以下条件的文档(属于同一集合):
- 有异性
- 在主要文档年龄偏好和主要文档之间有年龄(IF EXISTS)在外国文档偏好(即双向检查)之间有
age
(IF EXISTS)
我的尝试如下,但有两个问题:
$exists
不能在 $expr
内部使用 idk why
- 年龄查询是目前的一种方式
$lookup: {
"from": "appusers",
"let": { 'gen': "$gender",'pref': "$preference" },
"pipeline": [{
$match: {$expr: {
$and: [
{ $ne: ["$gender", "$$gen"]},
{ $or: [
{$exists: {"$age": false}},
{$and: [
{ $gte: ["$age", '$$pref.age_from' ] },
{ $lte: [ "$age", '$$pref.age_to' ] }
]}
]}
]
}}}],
"as": "matches"
}
示例:
输入文档:
{
name: "person1",
age: 36,
gender: "Male",
preference: {
age_from: 25,
age_to: 35
}
}
{
name: "person2",
age: 18,
gender: "Female",
preference: {
age_from: 25,
age_to: 40
}
}
{
name: "person3",
age: 26,
gender: "Female",
preference: {
age_from: 30,
age_to: 35
}
}
{
name: "person4",
age: 26,
gender: "Female",
preference: {
age_from: 30,
age_to: 40
}
}
输出:
对于第 1 个人,匹配数组将仅显示第 4 个人(同样第 4 个人匹配将显示第 1 个人)即:
{
name: person1,
age: 36,
gender: "Male",
preference: {
age_from: 28,
age_to: 35
},
matches: [
{
name: person4,
...
}
]
}
我看过 this and 但没有帮助
$exists
can't be used inside $expr
idk why
$expr Allows the use of aggregation expressions within the query language, and $exists不是聚合运算符,
您只需要更正两件事:
- 先把
$expr
条件放在$and
条件里面
- 将
$expr
放在最后一个$and
条件中
db.appusers.aggregate([
{
$lookup: {
from: "appusers",
let: { gen: "$gender", pref: "$preference" },
pipeline: [
{
$match: {
$and: [
{ $expr: { $ne: ["$gender", "$$gen"] } },
{
$or: [
{ age: { $exists: false } },
{
$expr: {
$and: [
{ $gte: ["$age", "$$pref.age_from"] },
{ $lte: ["$age", "$$pref.age_to"] }
]
}
}
]
}
]
}
}
],
as: "matches"
}
}
])
对于$exists
问题,你可以用$ifNull
包裹age
,然后用$eq
来检查是否存在。
对于 2 向年龄匹配,我认为您只需要为 person4 到 person1 重复从 person1 到 person4 的年龄匹配条件。尽管在您当前给定的测试用例中,由于 person4 的年龄不符合 person1 的偏好,因此找不到匹配项。
db.appusers.aggregate([
{
"$match": {
name: "person1"
}
},
{
$lookup: {
"from": "appusers",
"let": {
"a": "$age",
"gen": "$gender",
"pref": "$preference"
},
"pipeline": [
{
$match: {
$expr: {
$and: [
{
$ne: [
"$$gen",
"$gender"
]
},
{
$and: [
{
$or: [
{
$eq: [
{
"$ifNull": [
"$age",
"age-not-exists"
]
},
"age-not-exists"
]
},
{
$and: [
{
$gte: [
"$age",
"$$pref.age_from"
]
},
{
$lte: [
"$age",
"$$pref.age_to"
]
}
]
}
]
},
{
$or: [
{
$eq: [
{
"$ifNull": [
"$$a",
"age-not-exists"
]
},
"age-not-exists"
]
},
{
$and: [
{
$gte: [
"$$a",
"$preference.age_from"
]
},
{
$lte: [
"$$a",
"$preference.age_to"
]
}
]
}
]
}
]
}
]
}
}
}
],
"as": "matches"
}
}
])
这里是Mongo playground供您参考。
您可以使用 $eq undefined 作为字段 age 而不是 $exists
{
"from": "appusers",
"let": { 'gen': "$gender",'pref': "$preference" },
"pipeline": [{
$match: {$expr: {
$and: [
{ $ne: ["$gender", "$$gen"]},
{ $or: [
{$eq: ["$age" , undefined]},
{$and: [
{ $gte: ["$age", '$$pref.age_from' ] },
{ $lte: [ "$age", '$$pref.age_to' ] }
]}
]}
]
}}}],
"as": "matches"
}
我想在加入时添加多个条件。加入满足以下条件的文档(属于同一集合):
- 有异性
- 在主要文档年龄偏好和主要文档之间有年龄(IF EXISTS)在外国文档偏好(即双向检查)之间有
age
(IF EXISTS)
我的尝试如下,但有两个问题:
$exists
不能在$expr
内部使用 idk why- 年龄查询是目前的一种方式
$lookup: {
"from": "appusers",
"let": { 'gen': "$gender",'pref': "$preference" },
"pipeline": [{
$match: {$expr: {
$and: [
{ $ne: ["$gender", "$$gen"]},
{ $or: [
{$exists: {"$age": false}},
{$and: [
{ $gte: ["$age", '$$pref.age_from' ] },
{ $lte: [ "$age", '$$pref.age_to' ] }
]}
]}
]
}}}],
"as": "matches"
}
示例: 输入文档:
{
name: "person1",
age: 36,
gender: "Male",
preference: {
age_from: 25,
age_to: 35
}
}
{
name: "person2",
age: 18,
gender: "Female",
preference: {
age_from: 25,
age_to: 40
}
}
{
name: "person3",
age: 26,
gender: "Female",
preference: {
age_from: 30,
age_to: 35
}
}
{
name: "person4",
age: 26,
gender: "Female",
preference: {
age_from: 30,
age_to: 40
}
}
输出: 对于第 1 个人,匹配数组将仅显示第 4 个人(同样第 4 个人匹配将显示第 1 个人)即:
{
name: person1,
age: 36,
gender: "Male",
preference: {
age_from: 28,
age_to: 35
},
matches: [
{
name: person4,
...
}
]
}
我看过 this and
$exists
can't be used inside$expr
idk why
$expr Allows the use of aggregation expressions within the query language, and $exists不是聚合运算符,
您只需要更正两件事:
- 先把
$expr
条件放在$and
条件里面 - 将
$expr
放在最后一个$and
条件中
db.appusers.aggregate([
{
$lookup: {
from: "appusers",
let: { gen: "$gender", pref: "$preference" },
pipeline: [
{
$match: {
$and: [
{ $expr: { $ne: ["$gender", "$$gen"] } },
{
$or: [
{ age: { $exists: false } },
{
$expr: {
$and: [
{ $gte: ["$age", "$$pref.age_from"] },
{ $lte: ["$age", "$$pref.age_to"] }
]
}
}
]
}
]
}
}
],
as: "matches"
}
}
])
对于$exists
问题,你可以用$ifNull
包裹age
,然后用$eq
来检查是否存在。
对于 2 向年龄匹配,我认为您只需要为 person4 到 person1 重复从 person1 到 person4 的年龄匹配条件。尽管在您当前给定的测试用例中,由于 person4 的年龄不符合 person1 的偏好,因此找不到匹配项。
db.appusers.aggregate([
{
"$match": {
name: "person1"
}
},
{
$lookup: {
"from": "appusers",
"let": {
"a": "$age",
"gen": "$gender",
"pref": "$preference"
},
"pipeline": [
{
$match: {
$expr: {
$and: [
{
$ne: [
"$$gen",
"$gender"
]
},
{
$and: [
{
$or: [
{
$eq: [
{
"$ifNull": [
"$age",
"age-not-exists"
]
},
"age-not-exists"
]
},
{
$and: [
{
$gte: [
"$age",
"$$pref.age_from"
]
},
{
$lte: [
"$age",
"$$pref.age_to"
]
}
]
}
]
},
{
$or: [
{
$eq: [
{
"$ifNull": [
"$$a",
"age-not-exists"
]
},
"age-not-exists"
]
},
{
$and: [
{
$gte: [
"$$a",
"$preference.age_from"
]
},
{
$lte: [
"$$a",
"$preference.age_to"
]
}
]
}
]
}
]
}
]
}
}
}
],
"as": "matches"
}
}
])
这里是Mongo playground供您参考。
您可以使用 $eq undefined 作为字段 age 而不是 $exists
{
"from": "appusers",
"let": { 'gen': "$gender",'pref': "$preference" },
"pipeline": [{
$match: {$expr: {
$and: [
{ $ne: ["$gender", "$$gen"]},
{ $or: [
{$eq: ["$age" , undefined]},
{$and: [
{ $gte: ["$age", '$$pref.age_from' ] },
{ $lte: [ "$age", '$$pref.age_to' ] }
]}
]}
]
}}}],
"as": "matches"
}