您的当前位置:首页MongoDB 固定集合

MongoDB 固定集合

2023-11-12 来源:哗拓教育

MongoDB 固定集合(Capped Collections)是性能出色且有着固定大小的集合,对于大小固定,我们可以想象其就像一个环形队列,当集合空间用完后,再插入的元素就会覆盖最初始的头部的元素!

创建固定集合

我们通过createCollection来创建一个固定集合,且capped选项设置为true:

>db.createCollection("cappedLogCollection",{capped:true,size:10000})

还可以指定文档个数,加上max:1000属性:

>db.createCollection("cappedLogCollection",{capped:true,size:10000,max:1000})

判断集合是否为固定集合:

>db.cappedLogCollection.isCapped()

如果需要将已存在的集合转换为固定集合可以使用以下命令:

>db.runCommand({"convertToCapped":"posts",size:10000})

以上代码将我们已存在的 posts 集合转换为固定集合。

固定集合查询

固定集合文档按照插入顺序储存的,默认情况下查询就是按照插入顺序返回的,也可以使用$natural调整返回顺序。

>db.cappedLogCollection.find().sort({$natural:-1})
固定集合的功能特点

可以插入及更新,但更新不能超出collection的大小,否则更新失败,不允许删除,但是可以调用drop()删除集合中的所有行,但是drop后需要显式地重建集合。

在32位机子上一个cappped collection的最大值约为482.5M,64位上只受系统文件大小的限制。

固定集合属性及用法属性
  • 属性1:对固定集合进行插入速度极快
  • 属性2:按照插入顺序的查询输出速度极快
  • 属性3:能够在插入最新数据时,淘汰最早的数据
  • 用法
  • 用法1:储存日志信息
  • 用法2:缓存一些少量的文档
  • MongoDB 固定集合

    标签:选项设置   convert   查询   最大   log   mongod   rtt   否则   需要   

    小编还为您整理了以下内容,可能对您也有帮助:

    MongoDB怎样添加和查询集合数据

    MongoDB虽然也是一种数据库,不过它的数据是以键值对格式保存在集合里面的。今天咪咪我就来讲解一下MongoDB数据库怎样添加数据和查询数据。

    首先,启动MongoDB数据库(不会的可参考我的其他指南,这里不多说),然后再连接MongoDB数据库。如图,使用 mongo命令就可以连接MongoDB数据库了。

    如图,提示connecting to……,说明连接成功了。

    接着使用use 数据库名来打开或者新建数据库。如果数据库存在,就会打开对应的数据库,如果数据库不存在,则会创建一个新的数据库并且打开数据库。

    执行命令之后,就会出现这个提示,说明数据库打开了,并且现在开始使用这个数据库。

    如图,通过db.集合名.insert()就可以往集合中插入数据,集合名可以自己定义,如果集合不存在,则创建新的集合,然后插入数据,如果集合存在,则打开集合并插入数据。

    执行命令之后,提示“nInserted……”说明插入数据成功。

    之前也说过,MongoDB数据库里面的数据是键值对形式,所以如果想要插入多条数据,可以这样写,也就是键值对之间用逗号隔开。

    如果想要查询数据,则可以使用db.集合名.find()语句来查询。如果想要查询a集合里面的数据则用db.a.find()来查询。注意,find()表示查询全部的数据。

    执行语句之后,集合中所有的数据都会显示出来。

    如果想要查询出特定的数据,则可以在find里面添加键值对作为条件。比如我要查询name为mimi的数据则可以这样写。

    执行语句之后,就可以查询到对应的数据了。集合中包含有name:mimi的数据只有一条,所以就显示一条。到此,MongoDB添加和查询集合数据的方法就分享完了。

    如何在MongoDB中建立新数据库和集合

    由于Mongodb不是关系型数据库文件,实际上,它并不存在传统关系型数据库中的所谓ldquo;数据库rdquo;的概念,但不用担心,当你第

    创建Mongodb数据库

    由于Mongodb不是关系型数据库文件,实际上,它并不存在传统关系型数据库中的所谓“数据库”的概念,但不用担心,当你第一次新增数据时,mongodb就会以collection集合的形式进行保存和新建,而不需要你手工去新建立。下面是例子:

    1)列出当前的数据库

    MongoDB shell version: 1.8.1

    connecting to: test

    > show dbs -

    admin 0.03125GB

    local (empty)

    可以使用show dbs来列出当前有多少个数据库,上面看到的是有两个,分别是admin和local。

    2) 定义新的数据库名

    我们通过使用“use new-databasename”的语法去使用一个新的数据库,注意,即使你的数据库还没建立起来,依然可以这样使用,因为mongodb会在真正插入了数据后,才会真正建立起来。

    >use mkyongdb

    switched to db mkyongdb

    > show dbs

    admin 0.03125GB

    local (empty)

    注意,在use mkyongdb后,mkyongdb实际上还没真正建立起来,只是表明目前是在使用mkyongdb了。

    3)保存数据

    定义一个collection,名为“users”,然后插入数据,如下:

    > db.users.save( {username:"mkyong"} )

    > db.users.find()

    { "_id" : ObjectId("4dbac7bfea37068bd0987573"), "username" : "mkyong" }

    > show dbs -

    admin 0.03125GB

    local (empty)

    mkyongdb 0.03125GB

    可以看到,用db.users.find()可以找出已插入的数据。这个时候,,名为“users”的collection已经建立起来了,同时,数据库mkyongdb也建立起来了。

    mongoDB应用篇-mongo聚合查询

    如果我们在日常操作中,将部分数据存储在了MongoDB中,但是有需求要求我们将存储进去的文档数据,按照一定的条件进行查询过滤,得到想要的结果便于二次利用,那么我们就可以尝试使用MongoDB的聚合框架。

    前面我们在学习文档查询的过程中,也介绍过一些查询的操作符,其中就有一部分是简单的查询聚合函数,例如 count 、 distinct 、 group 等,如果是简单的数据分析过滤,完全可以使用这些自带的聚合函数以及查询的操作符来完成文档的过滤查询操作

    如果我们遇到了一些数据需要跨多个文本或者统计等操作,这个时候可能文档自身也较为复杂,查询操作符已经无法满足的时候,这个时候就需要使用MongoDB的聚合查询框架了。

    使用聚合框架可以对集合中的文档进行变换和组合查询,基本上我们使用的时候,都是使用多个构件创建一个管道,用于对一连串的文档进行处理。这里的构件包括 筛选(filter) 、 投射(projecting) 、 分组(grouping) 、 排序(sorting) 、 (limiting) 以及 跳过(skipping)

    MongoDB中需要使用聚合操作,一般使用 aggregate 函数来完成多个聚合之间的连接,aggregate() 方法的基本语法格式如下 :

    现在假设我们有个集合articles,里面存储了文章的集合,大致如下:

    但这时我们需要查询出来每一个作者写的文章数量,需要使用aggregate()计算 ,大致如下:

    输出的结果为:

    通过这个简单的案例我们就能输出想要的数据和属性名,大概分析一下刚刚的聚合查询语句, by_user字段进行分组,代表每个用户一条数据,而num_tutorial则是定义了数值类型计算的结果字段,$sum则是计算总和,相当于每个用户出现一次,都会+1,最终计算出来的总和通过num_tutorial字段进行输出

    注:如果管道没有给出预期的结果,就需要进行调试操作,调试的时候,可以尝试先给一个管道操作符的条件,如果这个时候查询出来的结果是我们想要的,那么我们需要再去指定第二个管道操作符,依次操作,最后就会定位到出了问题的操作符

    前面我们提到聚合查询会使用管道操作符,而每一个操作符就会接受一连串的文档,对这些文档进行一些类型转换,最后将转换以后的文档结果传递给下一个管道操作符来执行后续的操作,如果当前是最后一个管道操作符,那么则会显示给用户最后的文档数据。不同的管道操作符是可以按照顺序组合在一起使用,并且可以被重复执行多次,例如我们可以先使用$match然后再去、 match操作。

    match管道操作符可以使用$gt、$lt、$in等操作符,进行过滤,不过需要注意的是不能在$match管道操作符中使用空间地理操作符。

    在实际使用的过程中,尽可能的将 match操作符以后,再去投射或者执行分组操作的话,是可以利用索引的。

    相比较一般的查询操作而言,使用管道操作,尤其是其中的投射操作更加强大。我们可以在查询文档结束以后利用 $project 操作符从文档中进行字段的提取,甚至于我们可以重命名字段,将部分字段映射成我们想要展示出去的字段,也可以对一部分字段进行一些有意义的处理。需要注意的是, $project 操作符可以传入两个参数,第一个是需要处理的属性名称,第二个则是0或者1,如果传入1,则代表当前的属性是需要显示出来的,如果是0或者不写,默认都是代表这个字段不需要显示出来

    当然第二个参数也可以是一个表达式或者查询条件,满足当前表达式的数据也可以进行显示,接下来我们先准备一点数据:

    接下来,我们来查询,条件是item字段为abc,quantity要大于5,并且我们只要item和price字段的结果,其他都排除掉:

    可以看到结果为:

    如果我们想要在原基础上改变某个字段的名称,例如将item改为item_code,可以利用$来完成,如下:

    可以看到我们指定的名称item_code,而这个别名对应的字段item使用$作为前缀标记,代表将item字段映射为item_code,可以看到结果:

    我们在投影的时候,除了可以将某个字段映射成其他字段以外,还可以针对某个字段进行一些简单的运算,最常见的就是 四则运算 ,即

    加法( subtract )、乘法( divide )、求模( $mod ) ,

    除此之外,还支持对字段进行 关系运算 (大小比较( " eq" )、大于( " gte" )、小于( " lte" )、不等于( " ifNull" ) )、

    逻辑运算 (与( " or" )、非 ( " concat" )、截取( " toLower" ) )等

    我们基于上面的需求,假设每一个价格是按照元为单位,现在要求输出W为单位,那么我们就需要对price进行除法运算,如下:

    除此之外,我们也可以将计算完毕的price改名为priceW,即:

    可以看到输出的结果为:

    这时有一个需求,要求我们返回数据的同时还要yyyy-MM-dd格式的时间字符串,这个时候我们就需要对date字段进行时间函数和字符串混合处理了,如下:

    这里需要注意的一点是, year:" substr函数将date字段的结果截取成字符串即可实现拼接

    group的_id上,代表按照当前字段进行分组,例如,我们这里根据item进行分组:

    在我们针对某个字段进行分组以后,我们可以针对每个分组进行一些操作符的使用,常见的例如: $sum 、 $avg 、 $min 、 $max 、 $first 、 $last 。

    $avg 操作符用来返回每一个分组内的平均值

    现在我们基于前面item的分组,我们想要算出来每个组内的平均价格是多少,如下:

    $min 和 $max 操作符用于返回分组内最大的值和最小的值

    除了平均值以外,我们现在将最贵的和最便宜的价格也要列出来,这个时候就可以使用这两个操作符了,如下:

    $first 、 $last 则是可以获取当前分组中第一个或者最后一个的某个字段的结果,如下:

    除此之外,我们还可以在分组的时候使用数组操作符,例如 $addToSet 可以判断,当前数组如果不包含某个条件,就添加到当前数组中, $push 则不管元素是否存在,都直接添加到数组中

    注意:大部分管道操作符都是流式处理的,只要有新的文档进入,就可以对新的文档进行处理,但是 $group 代表必须收到全部文档以后才可以进行分组操作,才会将结果传递给后续的管道操作符,这就意味着,如果当前mongo是存在分片的,会先在每个分片上执行完毕以后,再把结果传递mongos进行统一的分组,剩下的管道操作符也不会在每个分片,而是mongos上执行了

    如果我们现在遇到一些文档比较复杂,比如存在内嵌文档的存在,某个属性里面嵌套了一个数组,但是我们需要对内嵌的数组文档进行分析过滤等查询处理,这个时候就可以使用 $unwind 操作符将每一个文档中的嵌套数组文件拆分为一个个的文档便于进行后续的处理,例如我们需要将之前的set集合中关于请求的url以及ip的信息拆分出来,原始的格式如下:

    我们可以使用命令进行拆分,如下:

    结果为:

    可以看到数据则是按照每一条信息的方式展示出来了,方便后续的计算以及输出,但是需要注意的一点是,这种方式,如果该文档中没有拆分的字段,或者是空数组,默认会直接排除,如果我们需要空数组等也输出计算出来,则可以指定 preserveNullAndEmptyArrays 参数,设置为true,则代表空数组或者不存在的文档也要拆分输出出来,即:

    我们可以在管道查询的过程中,按照某个属性值或者多个属性的结果进行顺序排序,排序的方式与普通查询操作符中的sort操作符表现一致,与其他管道操作符一样,可以在任何阶段使用,但是,需要注意的一点是,建议在管道操作符第一阶段进行排序,因为此时的排序是可以触发索引的,如果在后续阶段进行排序,会消耗大量内存,并且耗时会很久,尤其是在有 $group 的情况下,如果放在 $group 操作符后面,会发现等到的时间很久,不仅仅是无法触发索引的问题,还和 $group 操作符是等待所有数据完毕才会触发的特性有关,因此需要格外注意。

    结果如下,按照我们想要的结果进行了排序:

    limit,只返回前两条数据,如下:

    结果如下:

    除了 skip,与之前的查询操作符作用也是一样的,用于在已经查询完毕的结果集中跳过前N条数据以后进行返回,我们将$skip加在刚刚的查询后面,如下:

    这个时候可以看到返回的结果为空,什么结果都没有了,这是因为前一步管道已经了仅仅返回2条,而接着我们又跳过了前两条文档,因此返回的结果为空,我们将顺序调换一下,看看:

    可以看到结果如下,与刚才的结果无异:

    管道查询操作符有很多,除了上面学习的常用的部分,还有几十个,需要了解全部的可以参考官网:

    https://docs.mongodb.com/manual/reference/command/aggregate/

    除此之外,我们在学习的过程中了解到,部分查询操作符是可以触发索引的,例如 $project 、 $group 或者 $unwind 操作符,因此我们也建议 如果可以的话,尽量先使用这类管道操作符进行数据过滤,可以有效减少数据集大小和数量,而且管道如果不是直接从原先的集合中使用数据,那就无

    法在筛选和排序中使用索引 ,例如我们先进行管道操作,再去将过滤好的数据进行 $sort 排序,会导致无法使用索引,效率大幅度下降,因此如果我们需要涉及到 $sort 操作的时候,如果可以尽可能在最开始就处理,这个时候可以使用索引,效率较高,然后再去进行管道查询筛选与分组等其他操作,可以有效的提高查询的效率。另外需要注意的一点是,在 MongoDB中会对每一个管道查询做,例如某一步管道查询操作导致内存占用超过20%,这个时候就会报错,无法继续使用管道 ,因为mongoDB本身每次最大是16Mb的数据量,为了尽可能避免或者减少这种问题,建议可以考虑尽可能的使用 $match 操作符过滤无用数据,减少数据总大小。同时也 因为管道查询是多步执行,例如 $group 则是等待所有数据完毕才会执行,因此可能会导致整体执行时间较久 ,也因为这样,才不建议在较高的实时查询需求上使用管道和查询,而是在 设计的时候尽可能直接使用查询操作符进行数据查询,触发更多的索引,更快的销量查询出来想要的结果。

    显示全文