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 查询多对的主要内容,如果未能解决你的问题,请参考以下文章