首页 > 解决方案 > mongodb 使用 $in 查询多对

问题描述

我有一个names包含数据的集合(省略了_id):

{first:"John", last:"Smith"},
{first:"Alice", last:"Johnson"},
{first:"Bob", last:"Williams"},
...

并且{first, last}是唯一索引。

我想找到很多names类似的名字:

db.names.find({$or: [{first:"Alice", last:"Brown"}, {first:"Bob", last:"White"}, ...]}

我可以使用$in而不是$or简化此查询吗?

===

我在 MySQL 中知道以下查询:

SELECT * FROM names WHERE (first = 'Alice' AND last = 'Brown') OR (first = 'Bob' AND last = 'White') OR ...

可以简化为:

SELECT * FROM names WHERE (first, last) IN (('Alice', 'Brown'), ('Bob','White') OR ...)

但我无法在 MongoDB 中找到等效的查询语法。

标签: sqlmongodbmongodb-query

解决方案


以下查询可以为我们提供预期的输出:

db.names.find({
    $expr:{
        $in:[
            {
                "first":"$first",
                "last":"$last"
            },
            [
                {
                    "first" : "Alice",
                    "last" : "Johnson"
                },
                {
                    "first" : "Bob",
                    "last" : "Williams"
                }
            ]
        ]
    }
}).pretty()

数据集:

{
    "_id" : ObjectId("5d81c3b7a832f81a9e02337b"),
    "first" : "John",
    "last" : "Smith"
}
{
    "_id" : ObjectId("5d81c3b7a832f81a9e02337c"),
    "first" : "Alice",
    "last" : "Johnson"
}
{
    "_id" : ObjectId("5d81c3b7a832f81a9e02337d"),
    "first" : "Bob",
    "last" : "Williams"
}

输出:

{
    "_id" : ObjectId("5d81c3b7a832f81a9e02337c"),
    "first" : "Alice",
    "last" : "Johnson"
}
{
    "_id" : ObjectId("5d81c3b7a832f81a9e02337d"),
    "first" : "Bob",
    "last" : "Williams"
}

查询分析:此查询不会使用您创建的唯一索引,我建议使用 $or 查询。

以下是获奖计划:

$或查询:

{
    "stage" : "COLLSCAN",
    "filter" : {
        "$expr" : {
            "$in" : [
                {
                    "first" : "$first",
                    "last" : "$last"
                },
                {
                    "$const" : [
                        {
                            "first" : "Alice",
                            "last" : "Johnson"
                        },
                        {
                            "first" : "Bob",
                            "last" : "Williams"
                        }
                    ]
                }
            ]
        }
    },
    "direction" : "forward"
}

$in 查询:

{
"stage" : "SUBPLAN",
    "inputStage" : {
        "stage" : "FETCH",
        "inputStage" : {
            "stage" : "OR",
            "inputStages" : [
                {
                    "stage" : "IXSCAN",
                    "keyPattern" : {
                        "first" : 1,
                        "last" : 1
                    },
                    "indexName" : "first_1_last_1",
                    "isMultiKey" : false,
                    "multiKeyPaths" : {
                        "first" : [ ],
                        "last" : [ ]
                    },
                    "isUnique" : true,
                    "isSparse" : false,
                    "isPartial" : false,
                    "indexVersion" : 2,
                    "direction" : "forward",
                    "indexBounds" : {
                        "first" : [
                            "[\"Alice\", \"Alice\"]"
                        ],
                        "last" : [
                            "[\"Brown\", \"Brown\"]"
                        ]
                    }
                },
                {
                    "stage" : "IXSCAN",
                    "keyPattern" : {
                        "first" : 1,
                        "last" : 1
                    },
                    "indexName" : "first_1_last_1",
                    "isMultiKey" : false,
                    "multiKeyPaths" : {
                        "first" : [ ],
                        "last" : [ ]
                    },
                    "isUnique" : true,
                    "isSparse" : false,
                    "isPartial" : false,
                    "indexVersion" : 2,
                    "direction" : "forward",
                    "indexBounds" : {
                        "first" : [
                            "[\"Bob\", \"Bob\"]"
                        ],
                        "last" : [
                            "[\"White\", \"White\"]"
                        ]
                    }
                }
            ]
        }
    }
}

您可以看到索引在 $or 查询中被正确使用,而在 $in 查询中没有使用。


推荐阅读