gpt4 book ai didi

mongodb - 在不使用 unwind 的情况下匹配数组中的两个相等字段

转载 作者:可可西里 更新时间:2023-11-01 10:04:19 25 4
gpt4 key购买 nike

问题是给定的文档有两个数组,每个数组都包含文档作为它们的元素,我想找到本质上具有的文档:

"obj1.a" === "obj2.b"

所以给定示例文档,但实际上期望更大的数组,那么该怎么做呢?:

{
"obj1": [
{ "a": "a", "b": "b" },
{ "a": "a", "b": "c" }
],
"obj2": [
{ "a": "c", "b": "b" },
{ "a": "c", "b": "c" }
]
},
{
"obj1": [
{ "a": "a", "b": "b" }
],
"obj2": [
{ "a": "a", "b": "a" }
]
}

一种方法可能是将它们与 JavaScript 和 $where 进行比较运算符,但从 JavaScript 中循环大型数组听起来不太好。

另一种方法是使用聚合框架进行比较,但这涉及展开两个彼此重叠的数组,这会创建大量要在管道中处理的文档:

db.objects.aggregate([
{ "$unwind": "$obj1" },
{ "$unwind": "$obj2" },
{ "$project": {
"match": { "$eq": [ "$obj1.a", "$obj2.b" ] }
}},
{ "$group": {
"_id": "$_id",
"match": { "$max": "$match" }
}},
{ "$match": { "match": true } }
])

在关注性能的地方,很容易通过 $project 查看实际处理的文档数量。和 $group最终可能比集合中的原始文档大很多倍。

因此,为了做到这一点,必须有某种方式来比较数组元素,而无需执行 $unwind。在这些数组上并最终将文档重新组合在一起。这是怎么做到的?

最佳答案

您可以使用 $map 获得此类结果MongoDB 2.6 中引入的运算符。这通过获取一个输入数组并允许对每个元素计算一个表达式来产生一个新数组作为结果来操作:

db.objects.aggregate([
{ "$project": {
"match": {
"$size": {
"$setIntersection": [
{ "$map": {
"input": "$obj1",
"as": "el",
"in": { "$concat": ["$$el.a",""] }
}},
{ "$map": {
"input": "$obj2",
"as": "el",
"in": { "$concat": ["$$el.b",""] }
}}
]
}
}
}},
{ "$match": { "match": { "$gte": 1 } } }
])

此处与 $setIntersection 一起使用和 $size运营商。作为$map仅返回要比较的元素的属性值,最终得到两个仅包含这些值的数组。

唯一的问题是 $map 的“in”选项目前需要一个运算符出现在对象 {} 表示法中它的论点。你现在不能说:

"in": "$$el.a"

为了解决这个问题,我们使用 $concat 将字符串值与空字符串连接起来。其他运算符可用于不同类型的 even $ifNull这将是相当通用的并且可以解决“类型”问题

"in": { "$ifNull": [ "$$el.a", false ] }

$setIntersection包装这些,用于确定这些“集合”的哪些值相同,并将结果作为仅包含匹配值的另一个数组返回。

最后 $size这里的运算符是一种聚合方法,它以整数形式返回数组的实际“大小”。所以这可以用在下面$match然后过滤掉所有未返回 1 或更大“大小”值的结果。

基本上,这完成了在四个单独阶段中完成的所有工作,其中前两个阶段在两个简单的传递中呈指数增长要处理的文档数量,所有这些都没有增加作为输入接收的文档数量。

关于mongodb - 在不使用 unwind 的情况下匹配数组中的两个相等字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24028407/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com