2013-08-22 108 views
3

我在MongoDB中有一个包含以下文档的集合:MongoDB不在'_id'上使用复合索引

/* 0 */ 
{ 
    "T" : [ 
     374135056604448742 
    ], 
    "_id" : { 
     "#" : 7778532275691, 
     "ts" : ISODate("2013-07-26T02:25:00Z") 
    } 
} 

/* 1 */ 
{ 
    "T" : [ 
     1056188940167152853 
    ], 
    "_id" : { 
     "#" : 34103385525388, 
     "ts" : ISODate("2013-07-30T03:00:00Z") 
    } 
} 

/* 2 */ 
{ 
    "T" : [ 
     1056188940167152853 
    ], 
    "_id" : { 
     "#" : 34103385525388, 
     "ts" : ISODate("2013-07-30T03:18:00Z") 
    } 
} 

现在,我试图用下面的查询来查询一些文档。

db.entries.find({ 
    '_id.ts': {'$gte': beginTS, '$lte': endTS}, 
    '_id.#' : 884327843395156951 
    }).hint([('_id', 1)]).explain() 

按照我的理解,因为_id是复合领域,蒙戈始终保持指数_id,因此回答上面的查询,蒙戈应该用在“_id”的指数。然而,回答上述查询是如下:

{u'allPlans': [{u'cursor': u'BtreeCursor _id_', 
    u'indexBounds': {u'_id': [[{u'$minElement': 1}, {u'$maxElement': 1}]]}, 
    u'n': 2803, 
    u'nscanned': 4869528, 
    u'nscannedObjects': 4869528}], 
u'cursor': u'BtreeCursor _id_', 
u'indexBounds': {u'_id': [[{u'$minElement': 1}, {u'$maxElement': 1}]]}, 
u'indexOnly': False, 
u'isMultiKey': False, 
u'millis': 128415, 
u'n': 2803, 
u'nChunkSkips': 0, 
u'nYields': 132, 
u'nscanned': 4869528, 
u'nscannedAllPlans': 4869528, 
u'nscannedObjects': 4869528, 
u'nscannedObjectsAllPlans': 4869528, 
u'scanAndOrder': False, 

因为它可以观察到,MongoDB是做数据库的整个扫描发现的文件只是少数。我不知道这里到底怎么了。

我试着改变查询顺序,但结果相同。我不知道这里发生了什么。任何帮助,如果深表感谢。

UPDATE

我理解这里的细微差别。 _id不是复合索引,它仅仅是一个确切的索引。这意味着如果_id是一个文档,那么不管文档的结构和它可能具有多少嵌套attrs或子文档,_id索引将只包含_id字段的一个条目。这个条目假设是_id文件的散列,并将保持唯一。

+0

如果你运行db.entries.getIndexes(),你会得到什么? – Mason

+0

您误解了_id'是如何编入索引的。看到这个问题:http://stackoverflow.com/questions/7246434/expected-behaviour-of-compound-id-in-mongodb – WiredPrairie

回答

3

您正在使用一个对象作为密钥,但您在使用compund index这里是而不是

_id索引有点特别,因为它是自动创建的并且始终是唯一的。通常,_id索引是ObjectIdUUID或可能是integer或包含某种散列的字符串。 MongoDB支持复杂对象作为键。但是,对于MongoDB,这仍然只是一个文档。它可以与其他文档进行比较,并且具有相同字段和值的文档将相等。但是由于您没有创建索引键(并且无法手动创建该索引),因此MongoDB不知道它包含字段#和字段ts

另一方面,复合索引明确地指文档的字段,例如, {"product.quantity" : 1, "product.created" : -1}。这必须在索引创建时指定。

看来你试图基本上存储在你的主键的时间戳。 MongoDB的ObjectId已包含时间戳,因此您可以直接在ObjectIds上进行基于日期的范围查询。