mongodb - Mongo查询数组是子数组

标签 mongodb aggregation-framework

我正在寻找一个充当 $setIsSubset 的查询,但不考虑重复值。

例如,[1,1,2,3][1,2,3,4]的子集,因为集合没有重复值。

如何编写查询以使 [1,1,2,3] 不是 [1,2,3,4] 的子集?

预期输出的示例:

INPUT     |  TARGET  | RESULT
[1]        [1,2,3,4]   TRUE
[1,2,3]    [1,2,3,4]   TRUE
[1,1,2,3]  [1,2,3,4]   FALSE
[1,2,3,4]  [1,2,3,4]   TRUE
[1,3]      [1,2,3,4]   TRUE
[1,11,5]   [1,2,3,4]   FALSE
[1,2,2,3]  [1,2,3,4]   FALSE

最佳答案

我建议不要在 mongo 查询中进行如此繁重的处理,因为您可以使用任何编程语言轻松完成相同的任务。但是,如果您在 mongo 中仍然需要它,那么只要输入和目标数组都已排序,以下查询就可以获得预期的输出。

db.collection.aggregate([
    {
        $project:{
            "modifiedInput":{
                $reduce:{
                    "input":"$input",
                    "initialValue":{
                        "data":[],
                        "postfix":0,
                        "index":0,
                        "nextElem":{
                            $arrayElemAt:["$input",1]
                        }
                    },
                    "in":{
                        "data":{
                            $concatArrays:[
                                "$$value.data",
                                [
                                    {
                                        $concat:[
                                            {
                                                $toString:"$$this"
                                            },
                                            "-",
                                            {
                                                $toString:"$$value.postfix"
                                            }
                                        ]
                                    }
                                ]
                            ]
                        },
                        "postfix":{
                            $cond:[
                                {
                                    $eq:["$$this","$$value.nextElem"]
                                },
                                {
                                    $sum:["$$value.postfix",1]
                                },
                                0
                            ]
                        },
                        "nextElem": {
                            $arrayElemAt:["$input", { $sum : [ "$$value.index", 2] }]
                        },
                        "index":{
                            $sum:["$$value.index",1]
                        }
                    }
                }
            },
            "modifiedTarget":{
                $reduce:{
                    "input":"$target",
                    "initialValue":{
                        "data":[],
                        "postfix":0,
                        "index":0,
                        "nextElem":{
                            $arrayElemAt:["$target",1]
                        }
                    },
                    "in":{
                        "data":{
                            $concatArrays:[
                                "$$value.data",
                                [
                                    {
                                        $concat:[
                                            {
                                                $toString:"$$this"
                                            },
                                            "-",
                                            {
                                                $toString:"$$value.postfix"
                                            }
                                        ]
                                    }
                                ]
                            ]
                        },
                        "postfix":{
                            $cond:[
                                {
                                    $eq:["$$this","$$value.nextElem"]
                                },
                                {
                                    $sum:["$$value.postfix",1]
                                },
                                0
                            ]
                        },
                        "nextElem": {
                            $arrayElemAt:["$target", { $sum : [ "$$value.index", 2] }]
                        },
                        "index":{
                            $sum:["$$value.index",1]
                        }
                    }
                }
            }
        }
    },
    {
        $project:{
            "_id":0,
            "matched":{
                $eq:[
                    {
                        $size:{
                            $setDifference:["$modifiedInput.data","$modifiedTarget.data"]
                        }
                    },
                    0
                ]
            }
        }
    }
]).pretty()

数据集:

{
    "_id" : ObjectId("5d6e005db674d5c90f46d355"),
    "input" : [
        1
    ],
    "target" : [
        1,
        2,
        3,
        4
    ]
}
{
    "_id" : ObjectId("5d6e005db674d5c90f46d356"),
    "input" : [
        1,
        2,
        3
    ],
    "target" : [
        1,
        2,
        3,
        4
    ]
}
{
    "_id" : ObjectId("5d6e005db674d5c90f46d357"),
    "input" : [
        1,
        1,
        2,
        3
    ],
    "target" : [
        1,
        2,
        3,
        4
    ]
}
{
    "_id" : ObjectId("5d6e005db674d5c90f46d358"),
    "input" : [
        1,
        2,
        3,
        4
    ],
    "target" : [
        1,
        2,
        3,
        4
    ]
}
{
    "_id" : ObjectId("5d6e005db674d5c90f46d359"),
    "input" : [
        1,
        3
    ],
    "target" : [
        1,
        2,
        3,
        4
    ]
}
{
    "_id" : ObjectId("5d6e005db674d5c90f46d35a"),
    "input" : [
        1,
        5,
        11
    ],
    "target" : [
        1,
        2,
        3,
        4
    ]
}
{
    "_id" : ObjectId("5d6e005db674d5c90f46d35b"),
    "input" : [
        1,
        2,
        2,
        3
    ],
    "target" : [
        1,
        2,
        3,
        4
    ]
}

输出:

{ "matched" : true }
{ "matched" : true }
{ "matched" : false }
{ "matched" : true }
{ "matched" : true }
{ "matched" : false }
{ "matched" : false }

说明:为了避免消除相同的值,我们向每个值添加后缀计数器。例如,[1,1,1,2,3,3,4,4] 将变为 ["1-0","1-1","1-2","2-0","3- 0”、“3-1”、“4-0”、“4-1”、“4-2”]。输入数组和目标数组转换后,计算设置差值。如果设定差异的大小为零,则匹配。

关于mongodb - Mongo查询数组是子数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57762267/

相关文章:

mongodb - 使用 mongo-go-driver,如何有效地从 WriteError 中检索重复的字段名称?

python - Mongo Aggregate 所有文档的字典列表中值的总和

php - 使用 PDO 驱动程序连接到 MongoDB

mongodb - 将 mongodb 2 与 actix-web 3 一起使用时为 "there is no reactor running, must be called from the context of a Tokio 1.x runtime"

mongoDB 分片示例

node.js - 如何查询达到最高分排名的文档

ruby-on-rails - 与 Mongoid 聚合

mongodb - Cannot import example dataset(系统找不到指定的文件)

mongodb - 如何将数字 1 格式化为字符串 "01"以进行聚合?

mongodb - MongoDB 中的条件 $sum