mongodb 使用 $in 查询多对

Posted

技术标签:

【中文标题】mongodb 使用 $in 查询多对【英文标题】:mongodb query multiple pairs using $in 【发布时间】:2019-09-18 02:45:39 【问题描述】:

我有一个带有数据的集合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 中找到等效的查询语法。

【问题讨论】:

【参考方案1】:

以下查询可以得到我们预期的输出:

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查询中没有使用。

【讨论】:

$expr: $in:[ ... ] 看起来不像$or: [ ...] 简单:-( 两者都不是最佳的。只是为了寻找新的做事方式:)【参考方案2】:

对于这个mysql查询

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

可以在mongodb中用作

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

对于下面的mysql查询

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

你不能创建mongodb $in查询

db.names.find(
  $or: [
     first:  $in: ["John", "Alice", "Bob"]  ,
     last:  $in: ["Smith", "Johnson", "Williams" ]  ,
])

因为它也通过了这个结果

("John", "Johnson"),("John", "Williams"),("John", "Smith"),("John", "Williams")..

最好的方法是$or 提问

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

可能存在更好的解决方案。如果找到任何答案,我会更新我的答案。谢谢

【讨论】:

【参考方案3】:

是的,可以使用$in 根据多个值查询 MongoDb 集合。

尝试使用以下语法:

db.names.find.( field: $in: [<value1>, <value2>, ... <valueN> ] )

例如,在您的情况下,它看起来像:

db.names.find(first: $in: ["Alice","Brown","Bob", "White"])

【讨论】:

但我想搜索的不是单个属性,而是属性对。 MongoDB 不支持这种语法:db.names.find((first, last): $in: [('Alice', 'Brown'), ('Bob','White'),...]) :-(

以上是关于mongodb 使用 $in 查询多对的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB 原则:$in 需要一个数组 - 多对多关系

mongodb安装.

mongoDB 安装

MongoDB 通过配置文件启动及注册服务

MongoDB 通过配置文件启动及注册服务

458 MongoDB安装