如果您在过去几年中构建了中型到大型Web应用程序,则可能考虑将其基于开源LAMP或MEAN堆栈。 较早的LAMP堆栈使用Linux操作系统,Apache Web服务器,MySQL关系数据库和PHP编程语言。 MEAN使用MongoDB NoSQL数据库,Express后端Web应用程序框架,Angular应用程序平台和Node.js JavaScript运行时。 MEAN本质上是一个端到端JavaScript堆栈。 首字母缩写词没有明确提到Linux,但通常是Node下方的OS。
在这篇评论中,我将讨论现在版本4的MongoDB数据库。MongoDB是一个高度可扩展的可操作数据库,可在开源版本和商业企业版本中使用,它可以在本地运行或作为托管云服务运行。 托管云服务称为MongoDB Atlas。
[InfoWorld解释: 什么是云原生? 开发软件的现代方式 。 | 入门: Azure云迁移指南 。 •教程: Google Cloud入门 。 | 通过InfoWorld的云计算新闻通讯了解云计算的最新发展。 ]
MongoDB无疑是NoSQL数据库中最受欢迎的数据库。 其文档数据模型为开发人员提供了极大的灵活性,而其分布式体系结构则提供了极大的可伸缩性。 因此,通常选择MongoDB用于必须管理大量数据,得益于水平可伸缩性并处理不适合关系模型的数据结构的应用程序。
由于MongoDB适用于各种用例,因此通常提出它来代替关系数据库。 但是,尽管摆脱严格的模式约束通常是有益的,但要记住,没有文档数据库是通用的解决方案,甚至MongoDB都不是通用的。
MongoDB的起源
MongoDB背后的公司由互联网广告公司DoubleClick背后的团队于2007年以10gen的身份成立。 MongoDB数据库的最初动机是能够处理Internet广告所需的敏捷性和规模。 作为规模的一个例子,DoubleClick在2007年每秒提供400,000个广告,并且难以与当时的现有数据库一起执行。
MongoDB是一个基于文档的存储,在其之上还具有一个基于图形的存储。 其他NoSQL数据库是键值存储和基于列的存储。 各种NoSQL数据库都具有以2007年SQL关系数据库中不可能的方式进行扩展的能力,但是不同种类的NoSQL数据库具有不同的优势,劣势和用例。
作为操作数据库,MongoDB的主要NoSQL竞争对手包括Amazon DynamoDB(键值存储),Google Cloud BigTable(列存储),Google Cloud Datastore(文档存储),Redis(内存中,键值存储),Couchbase (多模型键值和文档存储), DataStax / Cassandra (列存储)和Azure Cosmos DB (包括SQL选项和多个NoSQL存储的多模型)。
什么是MongoDB?
MongoDB Inc.将MongoDB描述为“一个具有所需的可伸缩性和灵活性的文档数据库,它具有所需的查询和索引功能。” 为了解决这个问题,我们首先需要了解文档数据库的性质,这是NoSQL设计的一种。
文档数据库不是将强类型数据存储在具有关系数据库等固定模式的相关规范化表中,而是以反规范化形式存储在类似JSON的名称-值文档中的相关数据。 MongoDB实际上并不存储JSON,但是:MongoDB存储BSON(二进制JSON),它扩展了JSON表示形式(字符串)以包括其他类型,例如int , long , date , floating point , decimal128和地理空间坐标,如图所示。下图。 BSON文档包含一个或多个字段,并且每个字段包含特定数据类型的值, 包括数组,二进制数据和子文档 。 BSON还跟踪每个文档的大小,以实现高效查找。
MongoDB
在MongoDB网络研讨会的这张幻灯片中,Joe Drumgoole解释了BSON存储格式如何将类型信息添加到JSON文档中。 然后,这些类型可用于生成适当的索引,并在发出查询时将正确的类型返回给编程语言。
BSON输入将输入字段索引。 MongoDB可以使用数据的类型生成正确的索引类型,从而在数据的单个副本上生成多模式图形,地理空间,B树和全文本索引。 MongoDB使您可以在任何文档字段上创建索引。
MongoDB
如果您熟悉SQL数据库,则可以使用SQL到MongoDB的映射图将已知的SQL概念与MongoDB的概念进行匹配。
MongoDB具有数据库,集合(表),文档(行),字段(列),索引, $lookup或嵌入式文档(联接),主键,聚合管道和事务。 为了获得更好的性能并避免进行多文档事务,您可能希望在MongoDB中使用子文档和数组,而不是像在SQL数据库中那样以标准化形式存储数据。
MongoDB 4 确实具有多文档事务,这意味着即使必须标准化数据设计,您仍然可以获得ACID属性。 以前的版本没有。
就其价值而言,MongoDB代表告诉我,单文档事务处理了90%需要ACID属性的用例。 当客户在版本4之前需要ACID进行多文档交易时,他们基本上是在应用程序级别自己实现的。
默认情况下,MongoDB使用动态模式,有时称为无模式。 在单个集合的文件不需要具有相同的字段集,并为字段的数据类型可以集合中跨文档不同。 您可以随时更改文档结构。
但是,可以使用架构治理。 从MongoDB 3.6开始,MongoDB支持JSON模式验证。 要启用它,请在验证程序表达式中使用$jsonSchema运算符。 验证在更新和插入期间进行。
如您在下面的文档快照和MongoDB Atlas屏幕快照中所见,MongoDB具有自己的查询语言,该语言在Mongo Shell中, 在12种受支持的语言驱动程序API (以及来自社区的更多 支持 )中以及在Compass GUI和Atlas集合选项卡(数据资源管理器)。 MongoDB查询语言与SQL完全不同,但是两者之间或多或少存在直接映射。 我之所以说“或多或少”是因为关系数据库不支持嵌入式文档,但是MongoDB支持。 不一定全都好,正如您将在下一节中看到的那样。
MongoDB
除了Mongo Shell和Compass GUI,MongoDB正式支持10种编程语言的查询,并且非正式地由社区开发了更多语言。 Mongo Shell基本使用JavaScript表示法,但会自动打印所有结果。
MongoDB
在这里,我正在食物数据库中搜索低饱和脂肪的食物。 $lt运算符当然意味着“小于”。 我在MongoDB Atlas中使用了由MongoDB Inc与我共享的公共数据收集。
MongoDB聚合框架使用的流水线运算符大致等同于SQL GROUP BY和WHERE子句。 例如,以下查询使用MongoDB的用户组数据库在Mongo Shell中列出过去的事件以及每个事件的总RSVP:
> db.past_events.aggregate( [{'$match': {'batchID': 101, 'event.status': 'past', 'event.group.urlname': {'$in': ['Atlanta-MongoDB-User-Group', 'Austin-MongoDB-User-Group', 'Baltimore-MongoDB-Users-Group', 'Bangalore-MongoDB-User-Group', 'Belfast-MongoDB-User-Group', 'Bergen-NoSQL', 'Bordeaux-MongoDB-User-Group', 'Boston-MongoDB-User-Group']}}},
{'$group': {'_id': {'urlname': '$event.group.urlname', 'year': {'$year': '$event.time'}}, 'event_count': {'$sum': 1}, 'rsvp_count': {'$sum': '$event.yes_rsvp_count'}}},
{'$project': {'_id': 0, 'group': '$_id.urlname', 'year': '$_id.year', 'event_count': 1, 'rsvp_count': 1}}])
该查询将aggregate函数与$match , $in , $group , $sum和$project运算符一起使用,并返回以下内容:
{ "event_count" : 2, "rsvp_count" : 27, "group" : "Boston-MongoDB-User-Group", "year" : 2017 }
{ "event_count" : 5, "rsvp_count" : 94, "group" : "Boston-MongoDB-User-Group", "year" : 2016 }
{ "event_count" : 5, "rsvp_count" : 231, "group" : "Boston-MongoDB-User-Group", "year" : 2015 }
{ "event_count" : 3, "rsvp_count" : 175, "group" : "Boston-MongoDB-User-Group", "year" : 2014 }
{ "event_count" : 10, "rsvp_count" : 489, "group" : "Boston-MongoDB-User-Group", "year" : 2013 }
{ "event_count" : 12, "rsvp_count" : 444, "group" : "Boston-MongoDB-User-Group", "year" : 2012 }
{ "event_count" : 2, "rsvp_count" : 118, "group" : "Boston-MongoDB-User-Group", "year" : 2011 }
{ "event_count" : 6, "rsvp_count" : 84, "group" : "Atlanta-MongoDB-User-Group", "year" : 2011 }
{ "event_count" : 3, "rsvp_count" : 74, "group" : "Baltimore-MongoDB-Users-Group", "year" : 2012 }
{ "event_count" : 1, "rsvp_count" : 5, "group" : "Bergen-NoSQL", "year" : 2015 }
{ "event_count" : 15, "rsvp_count" : 286, "group" : "Atlanta-MongoDB-User-Group", "year" : 2012 }
{ "event_count" : 11, "rsvp_count" : 321, "group" : "Baltimore-MongoDB-Users-Group", "year" : 2013 }
{ "event_count" : 8, "rsvp_count" : 124, "group" : "Bangalore-MongoDB-User-Group", "year" : 2015 }
{ "event_count" : 6, "rsvp_count" : 381, "group" : "Bangalore-MongoDB-User-Group", "year" : 2013 }
{ "event_count" : 7, "rsvp_count" : 242, "group" : "Bangalore-MongoDB-User-Group", "year" : 2012 }
{ "event_count" : 13, "rsvp_count" : 233, "group" : "Atlanta-MongoDB-User-Group", "year" : 2013 }
{ "event_count" : 10, "rsvp_count" : 171, "group" : "Baltimore-MongoDB-Users-Group", "year" : 2014 }
{ "event_count" : 3, "rsvp_count" : 28, "group" : "Austin-MongoDB-User-Group", "year" : 2017 }
{ "event_count" : 2, "rsvp_count" : 52, "group" : "Austin-MongoDB-User-Group", "year" : 2016 }
{ "event_count" : 1, "rsvp_count" : 8, "group" : "Atlanta-MongoDB-User-Group", "year" : 2018 }
Type "it" for more
>
MongoDB还具有mapReduce函数。 Compass GUI具有一个聚合管道构建器,该构建器使创建诸如上述查询之类的查询非常简单。
MongoDB支持一系列服务器数据一致性级别, 从未提交读取开始到因果关系 。 因果一致性仅在3.6版中添加,并且在客户端会话中也受支持。 客户端设置读取和写入关注点以指定所需的一致性级别。
在MongoDB中,写操作是单个文档级别的原子操作,即使该操作修改了单个文档中的多个嵌入式文档。 当单个写入操作(例如db.collection.updateMany() )修改多个文档时,每个文档的修改都是原子的,但整个操作不是原子的。 从版本4.0开始,对于需要原子性来更新多个文档或读取多个文档之间保持一致性的情况,MongoDB为副本集提供了多文档事务,但会降低性能。