【问题标题】:Mongoose array elements ALL $in arrayMongoose 数组元素 ALL $in 数组
【发布时间】:2020-09-23 18:29:09
【问题描述】:

我有一个这样的数组:

{
    "_id" : ObjectId("581b7d650949a5204e0a6e9b"),
    "types" : [ 
        {
            "type" : ObjectId("581b7c645057c4602f48627f"),
            "quantity" : 4,
            "_id" : ObjectId("581b7d650949a5204e0a6e9e")
        }, 
        {
            "type" : ObjectId("581ca0e75b1e3058521a6d8c"),
            "quantity" : 4,
            "_id" : ObjectId("581b7d650949a5204e0a6e9e")
        }
    ],
    "__v" : 0
},
{
    "_id" : ObjectId("581b7d650949a5204e0a6e9c"),
    "types" : [ 
        {
            "type" : ObjectId("581b7c645057c4602f48627f"),
            "quantity" : 4,
            "_id" : ObjectId("581b7d650949a5204e0a6e9e")
        }
    ],
    "__v" : 0
}

我想创建一个查询,它将返回类型数组 ALL 与 $in 数组匹配的元素。

例如:

query([ObjectId("581b7c645057c4602f48627f"), ObjectId("581ca0e75b1e3058521a6d8c")])

应该返回元素 1 和 2

query([ObjectId("581b7c645057c4602f48627f")])

应该返回元素 2

query([ObjectId("581ca0e75b1e3058521a6d8c")])

应该什么都不返回

我试过了

db.getCollection('elements').find({'types.type': { $in: [ObjectId("581ca0e75b1e3058521a6d8c")]}})

但如果只有一种类型匹配,它会返回元素

【问题讨论】:

  • 为什么 query([ObjectId("581ca0e75b1e3058521a6d8c")]) 应该什么都不返回?
  • 因为没有元素只有 ObjectId("581ca0e75b1e3058521a6d8c")

标签: node.js arrays mongodb aggregation-framework


【解决方案1】:

您可能必须使用聚合,因为 $in 和 $elematch 将只返回匹配的元素。项目阶段确实设置了 equals 以创建一个全匹配标志,并在最后一个阶段匹配为真值。

aggregate([ {
    $project: {
        _id: 0,
        isAllMatch: {$setIsSubset: ["$types.type", [ObjectId("581b7c645057c4602f48627f")]]},
        data: "$$ROOT"
    }
}, {
    $match: {
        isAllMatch: true
    }
}])

样本输出

{
    "isAllMatch": true,
    "data": {
        "_id": ObjectId("581b7d650949a5204e0a6e9c"),
        "types": [{
            "type": ObjectId("581b7c645057c4602f48627f"),
            "quantity": 4,
            "_id": ObjectId("581b7d650949a5204e0a6e9e")
        }],
        "__v": 0
    }
}

替代版本:

此版本将项目和匹配阶段合并为一个 $redact 阶段,使用 $cond 运算符来决定是保留还是修剪元素。

aggregate([{
    "$redact": {
        "$cond": [{
                $setIsSubset: ["$types.type", [ObjectId("581b7c645057c4602f48627f")]]
            },
            "$$KEEP",
            "$$PRUNE"
        ]
    }
}])

【讨论】:

  • 我想返回元素,而不是类型。而且我认为 $setEquals 不起作用,因为我想验证 element 中的所有类型是否都在作为参数给出的数组中。
  • 它返回带有类型的元素。您可以将任何数组传递给组管道中的 isAllMatch。请准确更新您的帖子,以查看您传递的输出和输入。
  • 感谢您的回复。 $setEquals: ['$types.type', myTypes] 似乎没有完成这项工作。仅当 '$types.type' 作为与 myTypes 相同的元素时才成立。如果 $types.type 中的所有元素都在 myTypes 中,我希望它是真的。如果 $types.type = [1, 2] 和 myTypes = [1, 2, 3] 我想返回元素。现在,它不会返回它
  • 啊,我明白了。您提供的示例中从未提到过。让我看看我能做什么。
  • 它有效。非常感谢。有没有一种优雅的方式来返回整个元素,而不必复制所有子项?我的对象比这个示例中的复杂得多,必须复制所有内容似乎很痛苦......
猜你喜欢
  • 2021-10-10
  • 2018-05-31
  • 2014-08-03
  • 2020-04-18
  • 2019-08-09
  • 1970-01-01
  • 2014-12-29
  • 2020-07-08
  • 1970-01-01
相关资源
最近更新 更多