在上一个mongodb教程中,我们介绍了 RockMongo管理工具和GridFS分布式文件储存系统,在本节中我们会讨论mongodb中的固定集合(capped collection)和自动递增序列的介绍和使用。
一、固定集合(capped collection)
固定集合是固定大小的循环集合,它遵循插入顺序,支持创建、读取和删除操作的高性能。通过循环,它意味着当分配给集合的固定大小耗尽时,它将开始删除集合中最旧的文档,而不提供任何显式命令。
如果更新导致文档大小增加,则有上限的集合限制对文档的更新。由于capped集合按磁盘存储的顺序存储文档,因此它确保文档大小不会增加磁盘上分配的大小。有上限的集合最适合存储日志信息、缓存数据或任何其他大容量数据。
1、创建固定集合
为了创建一个有上限的集合,我们使用普通的createCollection命令,但是将capped选项设置为true并以字节为单位指定集合的最大大小。
>db.createCollection("cappedLogCollection",{capped:true,size:10000})
除了集合大小之外,我们还可以使用max参数限制集合中的文档数量:
>db.createCollection("cappedLogCollection",{capped:true,size:10000,max:1000})
如果你想检查一个集合是否有上限,可以使用下面的isCapped命令:
>db.cappedLogCollection.isCapped()
如果你计划将现有的集合转换为capped,则可以使用以下代码来完成:
>db.runCommand({"convertToCapped":"posts",size:10000})
这段代码将把我们现有posts集合转换成一个有上限的集合。
2、查询固定集
默认情况下,对于有上限的集合的find查询将按插入顺序显示结果。但是,如果希望以相反的顺序检索文档,可以使用sort命令,如下面的代码所示:
>db.cappedLogCollection.find().sort({$natural:-1})
关于有上限的集合,还有一些其他的要点值得了解
- 我们不能从一个有上限的集合中删除文档。
- 在一个有上限的集合中没有默认索引,甚至在_id字段中也没有。
- 在插入新文档时,MongoDB实际上不必在磁盘上寻找容纳新文档的位置。它可以盲目地将新文档插入集合的末尾,这使得在上限集合中的插入操作非常快。
- 类似地,在读取文档时,MongoDB以与磁盘上相同的顺序返回文档,这使得读取操作非常快。
二、自动递增序列
MongoDB不像SQL数据库那样具有开箱即用的自动增量功能,默认情况下它使用_id字段的12字节ObjectId作为唯一标识文档的主键,不过在某些情况下,我们可能希望_id字段具有一些除ObjectId之外的自动递增值。
自动递增序列通过使用计数器集合和JS函数的方式实现这一功能。
1、使用计数器集合
考虑以下产品文档,我们希望_id字段是一个自动递增的整数序列,从1、2、3、4一直到n。
{
"_id":1,
"product_name": "Samsung",
"category": "IT"
}
为此创建一个计数器集合,它将跟踪所有序列字段的最后一个序列值。
>db.createCollection("counters")
现在我们将在以pid为键的计数器集合中插入以下文档:
{
"_id":"pid",
"sequence_value": 0
}
字段sequence_value跟踪序列的最后一个值,使用以下代码将这个序列文档插入到计数器集合中:
>db.counters.insert({_id:"pid",sequence_value:0})
2、创建Javascript函数
现在我们将创建一个函数getNextSequenceValue,它将以序列名称作为输入,将序列号增加1并返回更新后的序列号。在我们的例子中,序列名是pid:
>function getNextSequenceValue(sequenceName){
var sequenceDocument = db.counters.findAndModify({
query:{_id: sequenceName },
update: {$inc:{sequence_value:1}},
new:true
});
return sequenceDocument.sequence_value;
}
3、使用Javascript函数
我们将在创建新文档并将返回的序列值赋值给文档的_id字段时使用函数getNextSequenceValue。
使用以下代码插入两个示例文档:
>db.products.insert({
"_id":getNextSequenceValue("pid"),
"product_name":"A",
"category":"IT"
})
>db.products.insert({
"_id":getNextSequenceValue("pid"),
"product_name":"B",
"category":"IT"
})
可以看到我们使用了getNextSequenceValue函数来设置_id字段的值,为了验证功能是否实现了,让我们使用find命令获取文档:
>db.products.find()
评论前必须登录!
注册