[mongo] 1.2 mongodb 数据库和集合

举报
dber 发表于 2021/01/21 17:51:32 2021/01/21
【摘要】 数据库和集合参考:https://docs.mongodb.com/manual/core/databases-and-collections/概述MongoDB将数据记录存储为文档 (特别是BSON文档),这些文档一起收集在集合中。一个 数据库存储一个或更多的文档集合。数据库在MongoDB中,数据库包含一个或多个文档集合。要选择要使用的数据库,使用use <db>创建数据库如果数据库不存...

数据库和集合

参考:https://docs.mongodb.com/manual/core/databases-and-collections/

概述

MongoDB将数据记录存储为文档 (特别是BSON文档),这些文档一起收集集合中。一个 数据库存储一个或更多的文档集合。

数据库

在MongoDB中,数据库包含一个或多个文档集合。要选择要使用的数据库,使用use <db>

创建数据库

如果数据库不存在,则在您第一次为该数据库存储数据时,MongoDB会创建该数据库。这样,您可以切换到不存在的数据库并在mongoshell中执行以下操作 :

复制
复制的
use myNewDB
db.myNewCollection1.insertOne( { x: 1 } )

insertOne()操作将同时创建数据库myNewDB和集合(myNewCollection1如果它们尚不存在)。确保数据库名称和集合名称均遵循MongoDB命名限制

集合

MongoDB将文档存储在集合中。集合类似于关系数据库中的表。

创建集合

如果不存在集合,则在您第一次为该集合存储数据时,MongoDB会创建该集合。

复制
复制的
db.myNewCollection2.insertOne( { x: 1 } )
db.myNewCollection3.createIndex( { y: 1 } ) 

如果insertOne()和 createIndex()操作都还不存在,则会创建它们各自的集合。确保集合名称遵循MongoDB命名限制

Explicit Creation

MongoDB提供了db.createCollection()使用各种选项显式创建集合的方法,例如设置最大大小或文档验证规则。如果未指定这些选项,则无需显式创建集合,因为在首次存储集合数据时,MongoDB会创建新集合。

要修改这些收集选项,请参见collMod

文档验证

3.2版中的新功能。

默认情况下,集合不要求其文档具有相同的架构。也就是说,单个集合中的文档不需要具有相同的字段集,并且字段的数据类型可以在集合中的不同文档之间有所不同。

但是,从MongoDB 3.2开始,您可以在更新和插入操作期间对集合强制执行文档验证规则。有关详细信息,请参见架构验证

修改文档结构

要更改集合中文档的结构,例如添加新字段,删除现有字段或将字段值更改为新类型,请将文档更新为新结构。

唯一标识符

3.6版的新功能。

注意

在featureCompatibilityVersion必须设置为"3.6"或更大。有关更多信息,请参见查看FeatureCompatibilityVersion

集合被分配了一个不变的UUID。在副本集的所有成员和分片群集中的分片中,集合UUID保持相同。

要检索集合的UUID,请运行 listCollections命令db.getCollectionInfos()法。


视图

MongoDB视图是可查询的对象,其内容由其他集合或视图上的聚合管道定义 。MongoDB不会将视图内容持久保存到磁盘。当客户端查询视图时,将按需计算视图的内容。MongoDB可以要求客户端 具有查询视图的权限。MongoDB不支持针对视图的写入操作。

例如:

  • 在员工数据集合上通过创建视图来排除私人或个人信息(PII)信息 。应用程序可以在视图中查询不包含任何PII的员工数据。
  • 传感器数据的集合上创建一个视图,add计算字段和度量。应用程序可以使用简单的查找操作来查询数据。
  • 创建一个视图,其joins两个集合分别包含库存和订单历史记录。应用程序可以查询联接的数据,而无需管理或了解底层的复杂管道。

当客户端查询视图时,MongoDB会将客户端查询追加到基础管道,并将该组合管道的结果返回给客户端。MongoDB可以将 聚合管道优化应用于组合管道。

注意

下页讨论视图。有关按需实例化视图的讨论,请参阅On-Demand Materialized Views

创建视图

要创建或定义视图:

  • 使db.createCollection()方法或 create令:

    复制
    复制的
    db.createCollection(
      "<viewName>",
      {
        "viewOn" : "<source>",
        "pipeline" : [<pipeline>],
        "collation" : { <collation> }
      }
    ) 
  • 使db.createView()法:

    复制
    复制的
    db.createView(
      "<viewName>",
      "<source>",
      [<pipeline>],
      {
        "collation" : { <collation> }
      }
    ) 

注意

  • 您必须在与源集合相同的数据库中创建视图。
  • 视图定义pipeline不能包含$out$merge阶段。如果视图定义包括嵌套管道(例如,视图定义包括 $lookup$facet段),则此限制也适用于嵌套管道。

行为

视图表现出以下行为:

索引使用和排序操作

  • 视图使用基础集合的索引。

  • 由于索引位于基础集合上,因此您不能直接在视图上创建,删除或重建索引,也不能在视图上获取索引列表。

  • 从MongoDB 4.4开始,您可以在视图上$natural 运行find命令时指定排序。MongoDB的早期版本不支持$natural视图排序。

  • 视图的基础聚合管道必须遵守100 MB的内存限制,才能阻止排序和阻止组操作。从MongoDB 4.4开始,您可以在视图上发出带有的 find命令,以允许MongoDB使用临时文件来阻止排序和组操作。allowDiskUse: true

    在MongoDB 4.4之前,只有aggregate命令接受该allowDiskUse选项。

    另外

    有关阻止排序操作内存限制的更多信息,请参见。Sort Operations

投影限制

find()视图上的操作不支持以下投影 运算符:

不可变名称

您不能重命名视图

视图创建

  • 视图是在读取操作期间按需计算的,并且MongoDB对视图执行读取操作,这是基础聚合管道的一部分。因此,视图不支持以下操作:
  • 如果用于创建视图的聚合管道禁止显示该 _id字段,则视图中的文档将没有该_id字段。

分片视图

如果视图的基础集合被分片,则认为它们是分片的。因此,对于通过在$lookup$graphLookup操作中的值无法指定分片视图。

视图和排序(Views and Collation)

    • 您可以 在创建时为视图指定默认排序规则。如果未指定排序规则,则视图的默认排序规则是“简单”二进制比较排序规则。也就是说,视图不会继承集合的默认排序规则。
    • 视图上的字符串比较使用视图的默认排序规则。尝试更改或覆盖视图的默认排序规则的操作将失败,并显示错误。
    • 如果从另一个视图创建视图,则不能指定与源视图的排序规则不同的排序规则。
    • 如果执行涉及多个视图的聚合(例如with$lookup或)$graphLookup,则这些视图必须具有相同的排序规则

    公共视图(Public View)定义

    列出集合的操作(例如 db.getCollectionInfos()和) db.getCollectionNames()在其输出中包括视图。

    重要

    视图定义是公共的;db.getCollectionInfos() ,explain对视图的操作将包括定义视图的管道。因此,请避免在视图定义中直接引用敏感字段和值。

    删除视图

    要删除视图,请使用视图上的db.collection.drop()法。

    修改视图

    您可以通过拖放并重新创建视图或使用collMod命令来修改视图。

    支持的操作

    以下操作提供对视图的支持,但本页中提到的限制除外:

    指令 方法
    create
    collMod  
     



    物化视图(On-Demand Materialized Views)

    从4.2版开始,MongoD对聚合管道 添加$merge的阶段。此阶段可以将管道结果合并到现有集合中,而不是完全替换该集合。此功能允许用户创建按需实例化视图,在该视图中,每次运行管道时都可以更新输出集合的内容。

    例子

    假设在2019年1月下旬左右,该集合bakesales 按项目包含销售信息:

    复制
    复制的
    db.bakesales.insertMany( [
       { date: new ISODate("2018-12-01"), item: "Cake - Chocolate", quantity: 2, amount: new NumberDecimal("60") },
       { date: new ISODate("2018-12-02"), item: "Cake - Peanut Butter", quantity: 5, amount: new NumberDecimal("90") },
       { date: new ISODate("2018-12-02"), item: "Cake - Red Velvet", quantity: 10, amount: new NumberDecimal("200") },
       { date: new ISODate("2018-12-04"), item: "Cookies - Chocolate Chip", quantity: 20, amount: new NumberDecimal("80") },
       { date: new ISODate("2018-12-04"), item: "Cake - Peanut Butter", quantity: 1, amount: new NumberDecimal("16") },
       { date: new ISODate("2018-12-05"), item: "Pie - Key Lime", quantity: 3, amount: new NumberDecimal("60") },
       { date: new ISODate("2019-01-25"), item: "Cake - Chocolate", quantity: 2, amount: new NumberDecimal("60") },
       { date: new ISODate("2019-01-25"), item: "Cake - Peanut Butter", quantity: 1, amount: new NumberDecimal("16") },
       { date: new ISODate("2019-01-26"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
       { date: new ISODate("2019-01-26"), item: "Cookies - Chocolate Chip", quantity: 12, amount: new NumberDecimal("48") },
       { date: new ISODate("2019-01-26"), item: "Cake - Carrot", quantity: 2, amount: new NumberDecimal("36") },
       { date: new ISODate("2019-01-26"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
       { date: new ISODate("2019-01-27"), item: "Pie - Chocolate Cream", quantity: 1, amount: new NumberDecimal("20") },
       { date: new ISODate("2019-01-27"), item: "Cake - Peanut Butter", quantity: 5, amount: new NumberDecimal("80") },
       { date: new ISODate("2019-01-27"), item: "Tarts - Apple", quantity: 3, amount: new NumberDecimal("12") },
       { date: new ISODate("2019-01-27"), item: "Cookies - Chocolate Chip", quantity: 12, amount: new NumberDecimal("48") },
       { date: new ISODate("2019-01-27"), item: "Cake - Carrot", quantity: 5, amount: new NumberDecimal("36") },
       { date: new ISODate("2019-01-27"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
       { date: new ISODate("2019-01-28"), item: "Cookies - Chocolate Chip", quantity: 20, amount: new NumberDecimal("80") },
       { date: new ISODate("2019-01-28"), item: "Pie - Key Lime", quantity: 3, amount: new NumberDecimal("60") },
       { date: new ISODate("2019-01-28"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
    ] ); 

    1.定义物化视图

    下updateMonthlySales功能定义了 monthlybakesales包含累积每月销售信息的实例化视图。在示例中,该函数采用日期参数以仅从特定日期开始更新每月销售信息。

    复制
    复制的
    updateMonthlySales = function(startDate) {
       db.bakesales.aggregate( [
          { $match: { date: { $gte: startDate } } },
          { $group: { _id: { $dateToString: { format: "%Y-%m", date: "$date" } }, sales_quantity: { $sum: "$quantity"}, sales_amount: { $sum: "$amount" } } },
          { $merge: { into: "monthlybakesales", whenMatched: "replace" } }
       ] );
    }; 
    • $match阶段过滤数据以仅处理大于或等于的销售startDate。

    • $group阶段按年月分组销售信息。此阶段输出的文档具有以下形式:


      {  “ _id”  : “ <YYYY-mm>” , “ sales_quantity”  : < num > , “ sales_amount”  : < NumberDecimal >  }
      
    • $merge阶段将输出写入 monthlybakesales集合。

      基于该_id字段(默认为unsharded输出集合),阶段检查中聚集结果文档相匹配的集合中的现有文档:

    2.执行初始运行

    对于初始运行,您可以输入日期:new ISODate("1970-01-01")

    复制
    复制的
    updateMonthlySales(new ISODate("1970-01-01")); 

    初始运行后,monthlybakesales包含以下文档;即 返回以下内容:db.monthlybakesales.find().sort( { _id: 1 } )


    { "_id" : "2018-12", "sales_quantity" : 41, "sales_amount" : NumberDecimal("506") }
    { "_id" : "2019-01", "sales_quantity" : 86, "sales_amount" : NumberDecimal("896") } 

    3.刷新物化视图

    假设到2019年2月的第一个星期,该bakesales 集合将使用更新的销售信息进行更新; 特别是1月和2月的销售量增加。

    复制
    复制的
    db.bakesales.insertMany( [
       { date: new ISODate("2019-01-28"), item: "Cake - Chocolate", quantity: 3, amount: new NumberDecimal("90") },
       { date: new ISODate("2019-01-28"), item: "Cake - Peanut Butter", quantity: 2, amount: new NumberDecimal("32") },
       { date: new ISODate("2019-01-30"), item: "Cake - Red Velvet", quantity: 1, amount: new NumberDecimal("20") },
       { date: new ISODate("2019-01-30"), item: "Cookies - Chocolate Chip", quantity: 6, amount: new NumberDecimal("24") },
       { date: new ISODate("2019-01-31"), item: "Pie - Key Lime", quantity: 2, amount: new NumberDecimal("40") },
       { date: new ISODate("2019-01-31"), item: "Pie - Banana Cream", quantity: 2, amount: new NumberDecimal("40") },
       { date: new ISODate("2019-02-01"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
       { date: new ISODate("2019-02-01"), item: "Tarts - Apple", quantity: 2, amount: new NumberDecimal("8") },
       { date: new ISODate("2019-02-02"), item: "Cake - Chocolate", quantity: 2, amount: new NumberDecimal("60") },
       { date: new ISODate("2019-02-02"), item: "Cake - Peanut Butter", quantity: 1, amount: new NumberDecimal("16") },
       { date: new ISODate("2019-02-03"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") }
    ] ) 

    要刷新monthlybakesales1月和2月的数据,请再次运行函数以重新运行聚合管道 new ISODate("2019-01-01")

    复制
    复制的
    updateMonthlySales(new ISODate("2019-01-01")); 

    的内容monthlybakesales已更新,以反映bakesales馆藏中的最新数据;即 返回以下内容:db.monthlybakesales.find().sort( { _id: 1 } )

    复制
    复制的
    {  “ _id”  : “ 2018-12” , “ sales_quantity”  : 41 , “ sales_amount”  : NumberDecimal (“ 506” ) }
    {  “ _id”  : “ 2019-01” , “ sales_quantity”  : 102 , “ sales_amount”  : NumberDecimal (“ 1142” ) }
    {  “ _id”  : “ 2019-02” , “ sales_quantity”  : 15 , “ sales_amount”  : NumberDecimal (“ 284” ) }
    

    Additional Information

    The $merge stage:

    • Can output to a collection in the same or different database.
    • Creates a new collection if the output collection does not already exist.
    • Can incorporate results (insert new documents, merge documents, replace documents, keep existing documents, fail the operation, process documents with a custom update pipeline) into an existing collection.
    • Can output to a sharded collection. Input collection can also be sharded.

    See $merge for:



    Capped Collections(固定集合)

    概述

    固定集合是固定大小的集合,它们支持高吞吐量操作,这些操作根据插入顺序插入和检索文档。固定集合的工作方式类似于循环缓冲区:一旦集合填充了其分配的空间,它就会通过覆盖集合中最旧的文档为新文档腾出空间。

    有关 创建固定集合的信息,请参见createCollection()create了解更多信息。

    建议:

    作为固定集合的替代方法,请考虑MongoDB的 TTL(生存时间)索引。如通过设置TTL从集合中使数据过期中所述,这些索引使您可以基于日期类型字段的值和索引的TTL值来使正常集合中的数据过期并删除。

    TTL索引与固定集合不兼容。

    特性

    插入顺序

    固定集合可确保插入顺序。查询不需要索引以插入顺序返回文档。没有索引开销,固定集合可以支持更高的插入吞吐量。

    自动删除最旧的文档

    为了给新文档腾出空间,有上限的集合会自动删除集合中最旧的文档,而无需脚本或显式删除操作。

    考虑以下用于固定集合的潜在用例:

    • 存储大容量系统生成的日志信息。在没有索引的情况下将文件插入具有上限的集合中,接近于将日志信息直接写入文件系统的速度非常快。此外,内置的先进先出属性可在管理存储使用的同时维护事件的顺序。
    • 在一个固定集合中缓存少量数据。由于缓存是读取而不是写入大量数据,因此您要么需要确保此集合始终保留在工作区域(即,在RAM中),要么需要为所需的一个或多个索引承担一定的写代价。

    例如,将操作日志存储在副本集中oplog.rs集合使用固定集合。从MongoDB 4.0开始,与其他设置固定集合不同,oplog可以超出其配置的大小限制,以避免删除majority commit point。

    _id索引

    固定集合 默认具有一个_id字段和该字段的索引_id。

    限制和建议

    更新

    如果您打算更新固定集合中的文档,请创建索引,以便这些更新操作不需要集合扫描。

    文档大小

    在版本3.2中更改。

    如果更新或替换操作更改了文档大小,会报错失败。

    文档删除

    您无法从固定集合中删除文档。要从集合中删除所有文档,请使用drop() 方法删除集合并重新创建固定集合。

    分片

    您无法将有固定集合分片。

    查询效率

    使用自然顺序可以有效地从集合中检索最近插入的元素。这(有点)类似于tail日志文件。

    合$out

    聚合管道阶段$out 无法将结果写入有固定集合。

    事务

    从MongoDB 4.2开始,您不能在事务中写入固定集合。事务中仍支持从固定集合中读取。

    程序

    创建固定集合

    您必须使用db.createCollection()方法显式创建带上限的集合 ,创建有固定集合时,必须指定集合的​​最大大小(以字节为单位),MongoDB将为该集合预先分配最大大小。固定集合的大小包括少量内部开销空间。

    复制
    复制的
    db.createCollection( "log", { capped: true, size: 100000 } ) 

    果size字段小于或等于4096,则集合的上限为4096字节。否则,MongoDB将提高提供的大小,使其成为256的整数倍。

    此外,您还可以使用max以下文档中的字段为集合指定最大文档数:

    复制
    复制的
    db.createCollection("log", { capped : true, size : 5242880, max : 5000 } ) 

    重要

    即使指定文档数,也始终需要该size参数。如果集合在达到最大文档数之前达到最大size限制,MongoDB将删除较旧的文档。

    查询固定集合

    find()在没有指定顺序的固定集合上执行,则MongoDB保证结果的顺序与插入顺序相同。

    要以相反的插入顺序检索文档,请 与参数设置为find()sort()方法一起$natural发出-1,如以下示例所示:

    复制
    复制的
    db.cappedCollection.find().sort( { $natural: -1 } ) 

    检查一个集合是固定集合

    使用isCapped()方法确定集合是否是固定集合,如下所示:

    复制
    复制的
    db.collection.isCapped() 

    将集合转换为固定集合

    使convertToCapped命令将非上限集合转换为上限集合:

    复制
    复制的
    db.runCommand({"convertToCapped": "mycoll", size: 100000}); 

    该size参数以字节为单位指定上限集合的大小。

    在操作期间,它将持有数据库exclusive lock 。其他操作将被阻止,直到该操作完成。请参阅一些常见的客户端操作采取了哪些锁?用于锁定数据库的操作。

    Tailable Cursor

    tailable cursor 与固定集合可以一起使用。与Unix  tail -f命令类似,tailable cursor “tails”有固定集合的最新数据。将新文档插入固定集合后,您可以使用tailable cursor 继续获取文档。

    有关创建Tailable Cursors光标信息参看Tailable Cursors

    【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
    • 点赞
    • 收藏
    • 关注作者

    评论(0

    0/1000
    抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。