MongoDB主键是您的朋友

MongoDB集合中的所有文档都有一个主键,称为_id 。 该字段在插入后自动分配给文档,因此几乎不需要提供它。 _id字段的有趣之处在于它是基于时间的 。 也就是说,基础类型的_id ,这是ObjectId ,是一个12字节的BSON型 ,和那些字节的4代表秒自Unix纪元。

_id字段的特殊之处还在于,它会通过在任何集合上调用getIndexes自动索引,如下所示。

所有MongoDB集合都有一个_id字段作为索引:

> db.things.getIndexes()
[
     {
          "v" : 1,
          "key" : {
               "_id" : 1
          },
          "ns" : "test.things",
          "name" : "_id_"
     }
]

就像每个人都记得传统RDBMS一样, 索引很重要,因为它们可以使文档检索更快。 但是,索引确实会占用内存,并且在插入文档时会稍微降低性能,因为必须更新所有相应的索引。 因此,尽管您应该认真考虑使用索引,但是在使用索引时需要经济。

自然地,仅当您知道文档的_id时才方便搜索。 通常会通过其他字段来搜索文档,如果您发现自己是通过时间序列 (例如created_at进行搜索的,那么您就来了。

想象一下名为logs的集合,其中包含捕获各种日志消息的简单文档。 示例文档如下所示:

日志收集中的一个简单文档:

{
     "_id" : ObjectId("51c4ab6d4d6906d494460728"),
     "message" : "crashed, no such method exception",
     "type" : "crash",
     "created_at" : ISODate("2013-06-21T19:37:17.992Z")
}

如果我想查找某个日期(例如今天)的所有日志消息怎么办? 我可以这样写查询:

查找自2013年6月20日以来创建的所有日志:

db.logs.find({created_at:{'$gt': new Date(2013, 5, 20)}})

如果我对该查询进行解释,则可以看到,因为我在created_at上没有索引,因此可以利用基本游标,并且扫描了集合中的所有文档以检索结果。

我的发现所附的解释计划:

> db.logs.find({created_at:{'$gt': new Date(2013, 5, 20)}}).explain()
{
     "cursor" : "BasicCursor",
     "isMultiKey" : false,
     "n" : 2,
     "nscannedObjects" : 4,
     "nscanned" : 4,
     "nscannedObjectsAllPlans" : 4,
     "nscannedAllPlans" : 4,
     "scanAndOrder" : false,
     "indexOnly" : false,
     "nYields" : 0,
     "nChunkSkips" : 0,
     "millis" : 0,
     "indexBounds" : {

     },
     "server" : "ghome-computer.home:27017"
}

如您所见,通过created_at字段进行搜索可能效率不高; 因此,您可能很想在该字段上添加索引。 这自然会使该特定查询效率更高,但是,您将招致新索引的开销,这将消耗更多的内存,并且由于对该新创建的索引进行了更新,因此插入操作会稍微慢一些。

事实证明,由于_id字段在其中嵌入了Unix纪元,因此无需添加 created_at字段,您就可以轻松地编写find表达式。 例如, MongoDB Ruby驱动程序允许您从Time来创建ObjectId ,如下所示:

通过from_time工厂方法创建一个新的ObjectId:

yesterday = Time.now - (60*60*(24*1))
custom_id = BSON::ObjectId.from_time(yesterday)
=> BSON::ObjectId('51c397800000000000000000')

如您所见,我通过from_time工厂方法创建了一个新的ObjectId 。 51c397800000000000000000是十六进制表示形式,前8位数字表示时间,其他所有内容均清零。

现在,我可以在任何find表达式中使用我的custom_id了。 通过Ruby驱动程序,我还可以将一个explain ,which'll展示自由的使用_id索引。

使用派生日期的ObjectId强制查找使用_id索引:

mongodb[:logs].find({_id: {'$gt' => custom_id}}).explain

=> {"cursor"=>"BtreeCursor _id_", "isMultiKey"=>false, "n"=>1, "nscannedObjects"=>1, "nscanned"=>1, ....}

如果看到BtreeCusor ,则表明您正在使用索引; 如果看到BasicCursor ,那么您知道不是。

因此,如果你发现自己在执行查询和创建了一段时间或日期字段比如索引created_at ,你可能会更好只使用蒙戈的_id领域,因为它已经嵌入在创建默认情况下,索引的概念。 数字?

参考: The Disco Blog博客中的MongoDB主键是我们的JCG合作伙伴 Andrew Glover的朋友

翻译自: https://www.javacodegeeks.com/2013/06/mongodb-primary-keys-are-your-friend.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值