您的位置:首页 > 编程语言 > Go语言

Mongo<=2.0.1 $and对索引的使用和$and如何工作

2012-02-01 13:59 323 查看

Mongo<=2.0.1 $and对索引的使用和$and如何工作

.Mongo:$and索引trap

下面是一些细节问题。自己在使用过程中遇到的。

[cpp] view plaincopyprint?

for (var i=0; i<1000000; i++) {

db.good.insert({"x":[i, i+1, i+2, i+3, i+4]});

}

向good中插入100W数据。

然后给x建立索引

ensureIndex({"x":1})

分别进行下面的搜索:

[cpp] view plaincopyprint?

db.good.find({"x":{"$gt":100}}).explain()

->

{

"cursor" : "BtreeCursor x_1",

"nscanned" : 4999505,

"nscannedObjects" : 4999505,

"n" : 999903

...

}

db.good.find({"x":{"$lt":100}})

->

{

"cursor" : "BtreeCursor x_1",

"nscanned" : 490,

"nscannedObjects" : 490,

"n" : 100

...

}

db.good.find({"$and":[{"x":{"$gt":100}}]}) //为什么没利用索引?? (include gte)

->

{

"cursor" : "BasicCursor",

"nscanned" : 1000000,

"nscannedObjects" : 1000000,

"n" : 999903

...

}

db.good.find({"$and":[{"x":{"$lt":100}}]}) (include lte)

->

{

"cursor" : "BtreeCursor x_1",

"nscanned" : 490,

"nscannedObjects" : 490,

"n" : 100

...

}

db.good.find({"$and":[{"x":101},{"x":{"$gt":100}}]}) // So, gt/gte操作不建议放在第一个

->

{

"cursor" : "BtreeCursor x_1",

"nscanned" : 5,

"nscannedObjects" : 5,

"n" : 5

...

}

2011.11.28 经证实 的确是mongobug: 详文:https://jira.mongodb.org/browse/SERVER-4180

While bumping from 1.8 to mongo 2.0.1, we noticed some query optimization seemed not to work anymore. After some laborious digging in our data, we found out a single document showing the issue.

Please open the attached .tgz. The tc.sh script will restore the document in a core.picture_set_pictures collection on a localhost:27017 mongo, setup an index, and explain a range query on a date embedded in a array of objects. The relevant section of the output shows.

"indexBounds" : { "votes.created_at" : [ [ ISODate("2010-10-31T13:37:20Z"), ISODate("292278995-01--2147483647T07:12:56.808Z") ] ] }

The upper bound is completely aberrant, and as far as I can tell, nothing in the document justifies such a value. As a consequence, on the real database, this will scan half of the table for every request. On the contrary, 1.8.3 was showing the right upper bound. Please also note that as far as we can tell, our collections have other instances of documents raising the problem (that is, a collection with just this document will exhibit the issue, but just removing the doc from the collection is not enough for the issue to disappear).

.....................>>另外关于自己对$and的整理:

[cpp] view plaincopyprint?

for (var i=0; i<1000000; i++) {

db.good.insert({"x":[i, i+1, i+2, i+3, i+4]})

}

db.good.find({"x":{"$gt":4,"$lt":5}})

{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e4"), "x" : [ 1, 2, 3, 4, 5 ] }

{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e5"), "x" : [ 2, 3, 4, 5, 6 ] }

{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e6"), "x" : [ 3, 4, 5, 6, 7 ] }

{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e7"), "x" : [ 4, 5, 6, 7, 8 ] }

这种操作有点类似$and操作。下面会说,但不是取交集的操作。尤其要注意。

如果需要 and关系 可以使用 $elemMatch

> db.good.find({"x":{"$elemMatch":{"$gt":4, "$lt":5}}})

>

db中没有符合 >4 and <5的数据 所以就没出来。

把lt改成lte

> db.good.find({"x":{"$elemMatch":{"$gt":4, "$lte":5}}})

{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e4"), "x" : [ 1, 2, 3, 4, 5 ] }

{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e5"), "x" : [ 2, 3, 4, 5, 6 ] }

{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e6"), "x" : [ 3, 4, 5, 6, 7 ] }

{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e7"), "x" : [ 4, 5, 6, 7, 8 ] }

{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e8"), "x" : [ 5, 6, 7, 8, 9 ] }

我们再来看下 2.0版本出来的 $and 操作是否可以取出正确的结果。

> db.good.find({"$and":[{"x":{"$gt":4}}, {"x":{"$lt":5}}]})

{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e4"), "x" : [ 1, 2, 3, 4, 5 ] }

{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e5"), "x" : [ 2, 3, 4, 5, 6 ] }

{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e6"), "x" : [ 3, 4, 5, 6, 7 ] }

{ "_id" : ObjectId("4ecf56d1aef0cdc1103012e7"), "x" : [ 4, 5, 6, 7, 8 ] }

结果也不是交集。而是匹配了 document中是否有x>4的值而且也必须有x<5的值。

$and和$elemMatch区别也就在与区间 即:1<x<5 按照$and理解:1<x and x<5 这里把1<x把5考虑进去了,同理x<5把1<x考虑进去了。

$and和不加$and的区别在于:

> db.good.find({"x":{"$lt":5,"$gt":1}})

{ "_id" : ObjectId("4ed061427ecbeebf00e65625"), "x" : [ 0, 1, 2, 3, 4 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e65626"), "x" : [ 1, 2, 3, 4, 5 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e65627"), "x" : [ 2, 3, 4, 5, 6 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e65628"), "x" : [ 3, 4, 5, 6, 7 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e65629"), "x" : [ 4, 5, 6, 7, 8 ] }

> db.good.find({"x":{"$lt":5}, "x":{"$gt":1}})

{ "_id" : ObjectId("4ed061427ecbeebf00e65625"), "x" : [ 0, 1, 2, 3, 4 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e65626"), "x" : [ 1, 2, 3, 4, 5 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e65627"), "x" : [ 2, 3, 4, 5, 6 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e65628"), "x" : [ 3, 4, 5, 6, 7 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e65629"), "x" : [ 4, 5, 6, 7, 8 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e6562a"), "x" : [ 5, 6, 7, 8, 9 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e6562b"), "x" : [ 6, 7, 8, 9, 10 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e6562c"), "x" : [ 7, 8, 9, 10, 11 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e6562d"), "x" : [ 8, 9, 10, 11, 12 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e6562e"), "x" : [ 9, 10, 11, 12, 13 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e6562f"), "x" : [ 10, 11, 12, 13, 14 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e65630"), "x" : [ 11, 12, 13, 14, 15 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e65631"), "x" : [ 12, 13, 14, 15, 16 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e65632"), "x" : [ 13, 14, 15, 16, 17 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e65633"), "x" : [ 14, 15, 16, 17, 18 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e65634"), "x" : [ 15, 16, 17, 18, 19 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e65635"), "x" : [ 16, 17, 18, 19, 20 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e65636"), "x" : [ 17, 18, 19, 20, 21 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e65637"), "x" : [ 18, 19, 20, 21, 22 ] }

{ "_id" : ObjectId("4ed061427ecbeebf00e65638"), "x" : [ 19, 20, 21, 22, 23 ] }

当这样使用的时候就需要$and了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: