MongoDb:在不同情况下搜索范围内的值

Esp*_*Esp 5 mongodb

第一。

我们在db中有以下记录

{ _id:1, values: [ 1 ,5 ,6 ,8]},
{ _id:2, values: [5 ,7 ,8,10 ,40 ,1]},
{ _id:3, values: [50 ,60 ,5 ,1 ]}
Run Code Online (Sandbox Code Playgroud)

我需要查询所有记录,其中包含范围8-10的“值”。 {_id:1},{_id:2}

query ({values:{'$gte':8,'$lte':10}}) 返回所有记录,由于“值”为数组,因此结果不正确!

第二。

我们在db中有以下记录

{_id:1, from: 1, to:100},
{_id:2, from: 101, to:200},
{_id:3, from: 201, to:300},
{_id:4, from: 301, to:400} ...
Run Code Online (Sandbox Code Playgroud)

我需要找到元素205在从到范围内的记录。结果{_id:3}

query({from:{'$lte':205},to:{'$gte':205})
Run Code Online (Sandbox Code Playgroud)

非常慢,根本不使用任何索引{from:1,to:1}

我有点困惑。有人可以帮忙吗?

谢谢。

Sam*_*cía 3

案例1:数组值的范围查询

编辑:我使用错误的值进行了测试。

正如文档所解释的,在数组值上使用条件运算符(AND 隐式运算符),只需要匹配一个条件即可返回文档。

所以,

  • _id:1 匹配 $lte 和 $gte 子句:确定
  • _id:2 匹配 $lte 和 $gte 子句:好的
  • _id:3 仅匹配 $lte (5 < 10 and 1 < 10) 子句:不好,但按文档说明的方式工作。

如果您需要使用此范围查询对数组值进行过滤,则必须使用对象包装这些值,如下所示:

db.test_col2.insert({values:[{v:1} ,{v:5 },{v:6} ,{v:8}]})
db.test_col2.insert({values:[{v:5 },{v:7} ,{v:8},{v:10 },{v:40} ,{v:1}]})
db.test_col2.insert({values: [{v:50} ,{v:60} ,{v:5} ,{v:1} ]})
db.test_col2.find({values: {$elemMatch:{v:{$lte:10, $gte:8}}} })

{"_id":ObjectId("51273098140d09d9105739b5"),"values":[{"v":1},{"v":5},{"v":6},{"v":8}]}
{"_id":ObjectId("51273098140d09d9105739b6"),"values":[{"v":5},{"v":7},{"v":8},{"v":10},{"v":40},{"v":1}]}
Run Code Online (Sandbox Code Playgroud)

如果你想在这个查询中使用索引,你可以这样做:

db.test_col2.ensureIndex({"values.v":1})
db.test_col2.find({values: {$elemMatch:{v:{$lte:10, $gte:8}}} }).explain()
{
  "cursor": "BtreeCursor values.v_1",
  "isMultiKey": true,
...
}
Run Code Online (Sandbox Code Playgroud)

案例 2:使用开盘区间触及指数

正如您所看到的,该查询按预期命中了索引。

for(var i=0 ; i<120000 ; i++) {
... db.test_col.insert({from: (Math.random()*100)%100, to: (Math.random()*100)%100});
... }
> db.test_col.ensureIndex({from:1, to:1})
> db.test_col.count()
120002
> db.test_col.find({from:{$gte:3}, to:{$lt:60}}).explain()
{
    "cursor" : "BtreeCursor from_1_to_1",
    "isMultiKey" : false,
    "n" : 69741,
    "nscannedObjects" : 69902,
    "nscanned" : 116563,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 340,
    "indexBounds" : {
        "from" : [
            [
                3,
                1.7976931348623157e+308
            ]
        ],
        "to" : [
            [
                -1.7976931348623157e+308,
                60
            ]
        ]
    },
    "server" : "new-host-2.home:27017"
}
Run Code Online (Sandbox Code Playgroud)