我的文档结构如下:
{
"input": {
"fields": [
{
"name": "last_name_hebrew",
"text": "test1",
},
],
},
"output": {
"fields": [
{
"name": "last_name_hebrew",
"text": "test1"
},
],
},
},
我想获取所有文档,其中字段具有名称为 last_name_hebrew
的对象,与 text
的 output.fields
值一样。
例如,在给定的结构中,它会返回此文档,因为 input.fields.name
是 last_name_hebrew
,而 text
等于 text
中的 output
。>
请注意,我不能保证 fields
或 input
中的 output
数组将在数组中包含 name: last_name_hebrew
。
我该怎么做?
这是我首先尝试强制数组具有 name
of last_name_hebrew
的文档:
db.collection.find({
"input.fields": {
$elemMatch: {
"name": "last_name_hebrew"
}
},
"output.fields": {
$elemMatch: {
"name": "last_name_hebrew"
}
},
})
但现在我需要比较 text
值。
答案 0 :(得分:1)
您必须使用聚合管道来实现这一点,有多种方法可以做到,这里是一个示例:
db.collection.aggregate([
{
$match: {
$expr: {
$gt: [
{
$size: {
$filter: {
input: "$input.fields",
as: "inputField",
cond: {
$and: [
{
$eq: [
"$$inputField.name",
"last_name_hebrew"
]
},
{
"$setIsSubset": [
[
"$$inputField.text"
],
"$output.fields.text"
]
}
]
}
}
}
},
0
]
}
}
}
])
Mongo Playground
需要注意的一件事是,对于此查询,对 output.fields.name
没有限制(因为它不是必需的),如果您确实需要名称匹配,那么您可以将 .text
字段放在 $setIsSubset
中{1}} 运算符。
答案 1 :(得分:1)
$elemMatch
的前 2 个条件是正确的last_name_hebrew
从input
中找到具有$filter
名称的匹配元素,然后使用$arrayElemAt
从过滤结果中获取第一个元素,过程相同output
字段,然后使用 $eq
db.collection.find({
"input.fields": { $elemMatch: { "name": "last_name_hebrew" } },
"output.fields": { $elemMatch: { "name": "last_name_hebrew" } },
$expr: {
$eq: [
{
$arrayElemAt: [
{
$filter: {
input: "$input.fields",
cond: { $eq: ["$$this.name", "last_name_hebrew"] }
}
},
0
]
},
{
$arrayElemAt: [
{
$filter: {
input: "$output.fields",
cond: { $eq: ["$$this.name", "last_name_hebrew"] }
}
},
0
]
}
]
}
});
第二个选项:如果您想更具体地匹配精确的 2 个字段 name
和 text
都只需要添加 $let
运算符以从过滤器返回字段,
db.collection.find({
"input.fields": { $elemMatch: { "name": "last_name_hebrew" } },
"output.fields": { $elemMatch: { "name": "last_name_hebrew" } },
$expr: {
$eq: [
{
$let: {
vars: {
input: {
$arrayElemAt: [
{
$filter: {
input: "$input.fields",
cond: { $eq: ["$$this.name", "last_name_hebrew"] }
}
},
0
]
}
},
in: { name: "$$input.name", text: "$$input.text" }
}
},
{
$let: {
vars: {
output: {
$arrayElemAt: [
{
$filter: {
input: "$output.fields",
cond: { $eq: ["$$this.name", "last_name_hebrew"] }
}
},
0
]
}
},
in: { name: "$$output.name", text: "$$output.text" }
}
}
]
}
})
第三个选项:为了更具体地检查循环中的两个字段,
$ne
检查返回结果是否为 [] 空db.collection.find({
"input.fields": { $elemMatch: { "name": "last_name_hebrew" } },
"output.fields": { $elemMatch: { "name": "last_name_hebrew" } },
$expr: {
$ne: [
{
$filter: {
input: {
$filter: {
input: "$input.fields",
cond: { $eq: ["$$this.name", "last_name_hebrew"] }
}
},
as: "i",
cond: {
$ne: [
{
$filter: {
input: "$output.fields",
cond: {
$and: [
{ $eq: ["$$this.name", "$$i.name"] },
{ $eq: ["$$this.text", "$$i.text"] }
]
}
}
},
[]
]
}
}
},
[]
]
}
})