[mongo] 1.2 mongodb 数据库和集合

网友投稿 818 2022-05-29

数据库和集合

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

概述

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

数据库

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

创建数据库

如果数据库不存在,则在您第一次为该数据库存储数据时,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命令:

复制

[mongo] 1.2 mongodb 数据库和集合

复制的

db.createCollection( "", { "viewOn" : "", "pipeline" : [], "collation" : { } } )

使用db.createView()方法:

复制

复制的

db.createView( "", "", [], { "collation" : { } } )

注意

您必须在与源集合相同的数据库中创建视图。

视图定义pipeline不能包含$out或$merge阶段。如果视图定义包括嵌套管道(例如,视图定义包括 $lookup或$facet阶段),则此限制也适用于嵌套管道。

行为

视图表现出以下行为:

只读

视图是只读的;对视图的写操作将出错。

以下读取操作可以支持视图:

db.collection.find()

db.collection.findOne()

db.collection.aggregate()

db.collection.countDocuments()

db.collection.estimatedDocumentCount()

db.collection.count()

db.collection.distinct()

索引使用和排序操作

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

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

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

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

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

另外

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

投影限制

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

$

$elemMatch

$slice

$meta

不可变名称

您不能重命名视图。

视图创建

视图是在读取操作期间按需计算的,并且MongoDB对视图执行读取操作,这是基础聚合管道的一部分。因此,视图不支持以下操作:

db.collection.mapReduce(),

$text运算符,因为$text聚合操作仅对第一阶段有效,

$geoNear 管线阶段。

如果用于创建视图的聚合管道禁止显示该 _id字段,则视图中的文档将没有该_id字段。

分片视图

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

视图和排序(Views and Collation)

您可以 在创建时为视图指定默认排序规则。如果未指定排序规则,则视图的默认排序规则是“简单”二进制比较排序规则。也就是说,视图不会继承集合的默认排序规则。

视图上的字符串比较使用视图的默认排序规则。尝试更改或覆盖视图的默认排序规则的操作将失败,并显示错误。

如果从另一个视图创建视图,则不能指定与源视图的排序规则不同的排序规则。

如果执行涉及多个视图的聚合(例如with$lookup或)$graphLookup,则这些视图必须具有相同的排序规则。

公共视图(Public View)定义

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

重要

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

删除视图

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

修改视图

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

支持的操作

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

db.createCollection()

db.createView()

db.getCollection()

db.getCollectionInfos()

db.getCollectionNames()

find

distinct

count

db.collection.aggregate()

db.collection.find()

db.collection.findOne()

db.collection.countDocuments()

db.collection.estimatedDocumentCount()

db.collection.count()

db.collection.distinct()

物化视图(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” : “ ” , “ 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:

More information on $merge and available options

Example: On-Demand Materialized View: Initial Creation

Example: On-Demand Materialized View: Update/Replace Data

Example: Only Insert New Data

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将删除较旧的文档。

参考

db.createCollection()和 create

查询固定集合

如果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。

MongoDB 云数据库 GaussDB(for Mongo) 数据库

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:高性能MySQL(二):服务器性能剖析
下一篇:GaussDB(DWS)数据库安全守护者之审计日志
相关文章