探索mongodb_探索MongoDB

探索mongodb

什么是MongoDB?

近年来,我们看到了对与传统关系模型不同的数据库管理系统的日益增长的兴趣。 它的核心是NoSQL的概念,该术语共同用于表示不使用结构化查询语言(SQL)与数据库进行交互的数据库软件。 NoSQL最著名的项目之一是MongoDB,这是一个面向文档的开源数据库,将数据存储在类似JSON的文档集合中。 MongoDB与其他NoSQL数据库的不同之处在于其强大的基于文档的查询语言,该语言使从关系数据库到MongoDB的转换变得容易,因为查询翻译非常容易。

MongoDB用C ++编写。 它将数据存储在类似JSON的文档中(使用BSON(JSON的二进制版本)),这些文档使用键/值对保存数据。 将MongoDB与其他文档数据库区分开来的一个功能是,将SQL语句转换为MongoDB查询函数调用非常简单。 这使得当前使用关系数据库的组织容易迁移。 它的安装和使用也非常简单,二进制文件和驱动程序可用于主要操作系统和编程语言。

MongoDB是一个开源项目,数据库本身已根据GNU AGPL(Affero通用公共许可证)3.0版获得许可。 该许可证是GNU GPL的修改版,它消除了一个漏洞,在该漏洞中,copyleft限制不适用于该软件的使用,仅适用于其分发。 当然,这对于存储在云中且通常不安装在客户端设备上的软件很重要。 使用常规的GPL,可以感觉到实际上没有进行分发,因此有可能绕开许可条款。

AGPL仅适用于数据库应用程序本身,不适用于MongoDB的其他元素。 允许开发人员从各种编程语言连接到MongoDB的官方驱动程序在Apache License Version 2.0下分发。 MongoDB文档可在知识共享许可下获得。

面向文档的数据库

面向文档的数据库与传统的关系数据库有很大的不同。 它们将数据存储在松散定义的文档中,而不是将数据存储在诸如表的严格结构中。 对于关系数据库管理系统(RDBMS)表,如果需要添加新列,则需要更改表本身的定义,这将把该列添加到每个现有记录中(尽管可能具有空值)。 这是由于RDBMS严格的基于架构的设计。 但是,使用文档可以将新属性添加到单个文档,而无需更改任何其他文档。 这是因为面向文档的数据库通常在设计上没有架构。

另一个基本区别是,面向文档的数据库不提供文档之间的严格关系,这有助于维护其无模式设计。 这与关系数据库有很大的不同,后者非常依赖于关系来规范化数据存储。 而不是将“相关”数据存储在单独的存储区域中,而是将它们嵌入文档本身中。 这比将引用存储到存储相关数据的另一个文档的引用要快得多,因为每个引用都需要附加查询。

这对于许多应用程序非常有效,在这些应用程序中,将数据独立包含在父文档中是有意义的。 一个很好的例子(在MongoDB文档中也给出了)是博客文章和评论。 这些评论仅适用于单个帖子,因此将它们与该帖子分开是没有意义的。 在MongoDB中,您的博客文章文档将具有as comments属性,用于存储该文章的评论。 在关系数据库中,您可能会有一个带有ID主键的注释表,一个带有ID主键的posts表和一个定义了哪些注释属于哪个post的中间映射表post_comments。 对于应该非常简单的东西来说,这是很多不必要的复杂性。

但是,如果必须分别存储相关数据,则可以使用单独的集合在MongoDB中轻松进行存储。 另一个很好的例子是您将客户订单信息存储在MongoDB文档中。 这通常可以包括有关客户,订单本身,订单中的订单项以及产品信息的信息。 使用MongoDB,您可能会将客户,产品和订单存储在单个集合中,但是您会将订单项数据嵌入相关的订单文档中。 然后,您将使用外键样式ID来引用productscustomers集合,就像在关系数据库中一样。 这种混合方法的简单性使得MongoDB对于习惯于使用SQL的人来说是一个绝佳的选择。 话虽如此,请花时间和精力来决定每种情况下需要采取的方法,因为通过将数据嵌入文档中而不是在其他集合中进行引用,可以显着提高性能。

功能一览

MongoDB不仅仅是基本的键/值存储。 让我们简要了解一下它的其他一些功能:

  • 官方二进制文件适用于Windows®,Mac OS X,Linux®和Solaris,源代码分发可用于自建
  • 适用于C,C#,C ++,Haskell,Java™,JavaScript,Perl,PHP,Python,Ruby和Scala的官方驱动程序,以及适用于其他语言的大量社区支持的驱动程序
  • 临时JavaScript查询,使您可以使用任何文档属性上的任何条件来查找数据。 这些查询反映了SQL查询的功能,使SQL开发人员可以很容易地编写MongoDB查询。
  • 支持查询中的正则表达式
  • MongoDB查询结果存储在游标中,该游标提供了一系列用于筛选,聚合和排序的函数,包括limit()skip()sort()count()distinct()group()
  • map/reduce实现高级聚合的实现
  • 使用GridFS的大文件存储
  • 类似于RDBMS的属性索引支持,您可以在其中直接在文档的选定属性上创建索引
  • 使用提示查询优化功能,说明计划和分析
  • 主/从复制类似于MySQL
  • 基于集合的对象存储,允许在需要标准化数据的地方进行引用查询
  • 具有自动分片的水平缩放
  • 就地更新以实现高性能的无争用并发
  • 在线外壳程序使您无需安装即可试用MongoDB
  • 深入的文档,几本书出版,目前正在写作

安装MongoDB

幸运的是,MongoDB非常容易安装在各种平台上。 二进制发行版适用于Windows,Mac OS X,Linux和Solaris,而各种程序包管理器为其他系统提供了简便的安装和设置选项。 如果您足够勇敢,则可以自己编译源代码。 在本节中,您将学习如何在Windows和Mac OS X上安装MongoDB,如何在Windows上将其设置为服务或在OS X上将其设置为守护程序。

在Windows上安装

在Windows上安装MongoDB非常简单。 在您喜欢的Web浏览器中,导航到http://www.mongodb.org/downloads并下载Windows的最新稳定生产版本。 建议使用64位版本,但只有在使用Windows操作系统的64位版本时才能使用。 如果不确定,请使用32位版本。

将压缩文件解压缩到C:\驱动器,这将创建一个新文件夹,其名称类似于mongodb-win32-i386-1.6.4。 为了使您的生活更轻松,请将此文件夹重命名为mongo。 接下来,您需要创建一个数据目录。 在Windows资源管理器中,转到C:\驱动器的根目录并创建一个名为data的新文件夹。 在此文件夹中,创建一个名为db的新文件夹。

现在,您可以启动MongoDB服务器。 使用Windows资源管理器导航到C:\ mongo \ bin,然后双击mongod.exe。 关闭打开的命令提示符窗口将停止MongoDB服务器。 因此,将MongoDB服务器设置为Windows控件的服务更加方便。 现在开始吧。

打开命令提示符窗口( 开始>运行> ,输入cmd并按OK )并发出清单1中的命令。

清单1.将MongoDB服务器设置为服务
> cd \mongo\bin
> mongod --install --logpath c:\mongo\logs --logappend 
--bind_ip 127.0.0.1 --directoryperdb

您应该在清单2中看到输出。

清单2.服务创建成功
all output going to c:\mongo\logs
Creating service MongoDB.
Service creation successful.
Service can be started from the command line via 'net start "MongoDB"'.

将Mongo作为服务安装后,现在可以使用以下命令启动它: > net start "MongoDB"

您应该在清单3中看到输出。

清单3. Mongo成功启动
The Mongo DB service is starting.
The Mongo DB service was started successfully.

现在,您可以运行MongoDB Shell客户端。 如果打开了命令提示符窗口,请确保您位于c:\ mongo \ bin文件夹中,然后输入以下命令: > mongo

或者,在Windows资源管理器中,导航到C:\ mongo \ bin并双击mongo.exe。 无论选择哪种方式启动Shell,都应该看到如清单4所示的提示。

清单4.启动shell
MongoDB shell version: 1.8.1
connecting to: test
>

除非您还希望在Mac OS X机器上设置MongoDB,否则现在可​​以跳过本节的下一部分,转到“入门”,在那里您将学习如何使用Shell客户端与MongoDB服务器进行交互。

在Mac OS X上安装

假设您使用的是64位版本的Mac OS X,以下步骤详细说明了如何下载MongoDB的64位OS X二进制文件,将其解压缩并进行配置以开始使用。 它还将向您展示如何将MongoDB作为守护程序运行。

首先,启动Terminal( 应用程序>实用程序> Terminal )。 在Terminal窗口中,运行清单5中的命令。

清单5.在Mac OS X上设置MongoDB
$ cd ~
$ curl http://fastdl.mongodb.org/osx/mongodb-osx-x86_64-1.6.4.tgz > mongo.tgz
$ tar xzf mongo.tgz
$ mv mongodb-osx-x86_64-1.8.1/ mongo
$ mkdir -p /data/db

MongoDB现在已设置并可以使用。 在继续之前,最好将MongoDB添加到您的路径中。 执行以下命令: $ nano ~/.bash_profile

该文件可能还不存在。 无论如何,添加以下行: export PATH={$PATH}:~/mongo/bin

通过按ctrl + O保存文件,然后在提示时按Enter。 然后按Ctrl + X退出nano。 现在,使用以下命令重新加载bash配置文件: $ source ~/.bash_profile

您现在可以启动MongoDB。 要启动它,只需发出以下命令: $ mongod

这将启动MongoDB数据库服务器作为前台进程。 如果您希望在后台将MongoDB作为守护进程启动,请发出以下命令: $ sudo mongod --fork --logpath /var/log/mongodb.log --logappend

系统将要求您输入密码; 在此提示符下输入Mac OS X管理员密码。

无论选择哪种方法启动MongoDB,服务器现在都应正在运行。 如果在前台启动,则需要一个单独的“终端”选项卡或窗口来启动客户端。 要启动客户端,只需使用以下命令: $ mongo

您应该在清单6中看到提示。

清单6.盯着客户
MongoDB shell version: 1.8.1
connecting to: test
>

在下一节中,您将学习如何使用MongoDB Shell创建数据库,集合,文档等。

使用MongoDB入门

Shell应用程序随MongoDB发行版一起提供,使您可以完全控制数据库。 使用该外壳,您可以使用服务器端JavaScript函数来创建和管理数据库,集合,文档和索引。 这样可以轻松快速地启动和运行MongoDB。 在本节中,您将学习如何启动外壳程序,并查看一些用于执行基本数据存储和检索的基本命令的示例。

MongoDB外壳

MongoDB发行版随附在bin文件夹中的MongoDB Shell应用程序。 在Windows上,这是应用程序mongo.exe的形式。 在Windows资源管理器中双击该程序将启动外壳程序。 在基于UNIX®的操作系统(包括Mac OS X)中,可以通过在终端窗口中执行mongo命令来启动MongoDB Shell(假设您已按照上述说明将MongoDB目录添加到路径中)。

首次启动该Shell时,应该会在清单7中看到消息。

清单7.启动shell之后的消息
MongoDB shell version: 1.8.1
connecting to: test
>

现在,您已连接到本地MongoDB服务器,尤其是“测试”数据库。 在下一部分中,您将学习如何创建数据库,文档和集合。 如果您在任何阶段都需要帮助,则只需在Mongo shell提示符下发出命令“ help”即可。 图1显示了help命令的典型输出。

图1. Mongo shell help命令的输出
Mongo Shell帮助命令的输出

如果您想查看MongoDB函数背后的源代码,只需在外壳中键入该函数的名称,它将打印JavaScript源。 例如,键入connect并按回车键,您将看到用于连接到MongoDB数据库的源代码。

创建数据库,集合和文档

默认情况下,Mongo Shell连接到“测试”数据库。 要切换到其他数据库,请使用“ use dbname”命令。 如果该数据库不存在,则在向其中添加任何数据后,MongoDB就会立即创建它。 让我们> use mymongo以下命令切换到“ mymongo”数据库: > use mymongo

外壳程序应返回以下消息: switched to db mymongo

此时,数据库仍然不存在,因为它不包含任何数据。 在MongoDB中,数据存储在集合中,允许您根据需要分隔文档。 让我们创建一个文档并将其存储在名为“ colors”的新集合中: > db.colors.save({name:"red",value:"FF0000"});

我们通过查询数据库来验证文档是否已存储: > db.colors.find();

您应该看到类似于以下内容的响应( _id属性是唯一标识符,并且结果可能会有所不同): { "_id" : ObjectId("4cfa43ff528bad4e29beec57"), "name" : "red", "value" : "FF0000" }

MongoDB中的文档存储为BSON(二进制JSON)。 使用Mongo Shell,我们可以使用类似于JSON的语法插入数据,其中每个文档都是键值对的对象。 在此示例中,我们创建了一个具有两个属性的文档: namevalue ,它们分别具有redFF0000 (标准红色的十六进制表示)的值。

您可能已经注意到,您不需要预先定义colors集合,当您使用保存功能插入项目时,这会自动完成。

在此示例中,您创建了一个非常简单的文档。 但是,可以使用所使用的类似JSON的语法来创建更复杂的文档。 考虑以下JSON文档,该文档代表采购订单或发票(请参见清单8 )。

清单8.创建一个简单的文档
{
    order_id: 109384,
    order_date: new Date("12/04/2010"),
    customer: {
        name: "Joe Bloggs",
        company: "XYZ Inc.",
        phone: "(555) 123-4567"
    },
    payment: {
        type: "Cash",
        amount: 4075.99,
        paid_in_full: true
    },
    items: [
        {
            sku: "ABC1200",
            description: "A sample product",
            quantity: 1,
            price_per_unit: 75.99,
        }, {
            sku: "XYZ3400",
            description: "An expensive product",
            quantity: 2,
            price_per_unit: 2000
        }
    ],
    cashier_id: 340582242
}

如您所见,这些文档可以存储各种数据类型,包括字符串,整数,浮点数,日期,对象,数组等。 在清单8中,订单项已直接嵌入到订单文档中,这使得稍后查询文档时检索该信息的速度更快。

由于MongoDB Shell使用JavaScript,因此在与数据库交互时可以编写常规JavaScript结构。 以清单9为例,该清单创建了一个字符文档集合,每个字符文档包含字符的字符串表示形式及其关联的ASCII代码。

清单9.创建字符文档的集合
> var chars = "abcdefghijklmnopqrstuvwxyz"
> for(var i =0; i<chars.length; i++) {    
... var char = chars.substr(i, 1);          
... var doc = {char:char, code: char.charCodeAt(0)};
... db.alphabet.save(doc);
... }

此循环将创建26个文档,每个字母对应一个小写字母,每个文档包含字符本身及其ASCII字符代码。 在下一节中,您将看到如何以各种方式检索此数据。

检索数据

在上一节中,您不仅学习了如何将数据插入到MongoDB数据库中,而且实际上还学习了如何使用最基本的数据检索功能find。 首先,在上一节末尾创建的字母集合上使用find命令: db.alphabet.find();

这将生成类似于清单10的响应。

清单10.生成的响应
> db.alphabet.find()
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8c"), "char" : "a", "code" : 97 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8d"), "char" : "b", "code" : 98 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8e"), "char" : "c", "code" : 99 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8f"), "char" : "d", "code" : 100 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec90"), "char" : "e", "code" : 101 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec91"), "char" : "f", "code" : 102 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec92"), "char" : "g", "code" : 103 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec93"), "char" : "h", "code" : 104 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec94"), "char" : "i", "code" : 105 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec95"), "char" : "j", "code" : 106 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec96"), "char" : "k", "code" : 107 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec97"), "char" : "l", "code" : 108 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec98"), "char" : "m", "code" : 109 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec99"), "char" : "n", "code" : 110 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec9a"), "char" : "o", "code" : 111 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec9b"), "char" : "p", "code" : 112 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec9c"), "char" : "q", "code" : 113 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec9d"), "char" : "r", "code" : 114 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec9e"), "char" : "s", "code" : 115 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec9f"), "char" : "t", "code" : 116 }
has more
>

默认情况下, find()函数检索集合中的所有文档,但仅显示前20个文档。 给出该命令it它将检索剩余的6个文档(请参见清单11 )。

清单11.检索剩余的6个文档
> it
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca0"), "char" : "u", "code" : 117 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca1"), "char" : "v", "code" : 118 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca2"), "char" : "w", "code" : 119 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca3"), "char" : "x", "code" : 120 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca4"), "char" : "y", "code" : 121 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca5"), "char" : "z", "code" : 122 }
>

find()函数实际上将游标返回到查询的结果集,在这种情况下,将retrieve all documents 。 如果未将其分配给变量或不执行其他功能,则默认情况下它将在屏幕上打印样本结果集。 要显示所有结果集,我们可以使用以下命令: > db.alphabet.find().forEach(printjson);

这将打印结果集中的每条记录,而不是显示一个子集。 接下来,我们将看到更多有关使用游标和查询来过滤数据的信息。

查询数据

MongoDB的最大优势之一是它对即席查询的强大支持,该查询的工作方式与传统关系数据库几乎相同,尽管过滤并返回了BSON文档而不是表行。 这种方法使它与其他文档存储区分开来,这对于SQL开发人员而言通常很难掌握。 使用MongoDB,可以将相对复杂SQL查询轻松转换为JavaScript函数调用。 在本节中,您将学习各种可用功能,这些功能可让您查询MongoDB中的数据,以及如何设置索引来帮助优化查询,就像在DB2,MySQL或Oracle中一样。

基本查询

在上一节中,您学习了如何使用查找功能来检索所有文档。 find函数接受一系列参数,这些参数使您可以过滤返回的结果。 例如,在我们之前创建的字母集合中,您可以使用以下命令找到“ char”属性值为“ q”的任何记录: > db.alphabet.find({char: "o"});

这将返回以下响应: { "_id" : ObjectId("4cfa4adf528bad4e29beec9a"), "char" : "o", "code" : 111 }

如果要返回代码小于或等于100的所有字符,则可以使用以下命令: > db.alphabet.find({code:{$lte:100}});

如您所料,这将返回清单12中的结果。

清单12.结果
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8c"), "char" : "a", "code" : 97 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8d"), "char" : "b", "code" : 98 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8e"), "char" : "c", "code" : 99 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8f"), "char" : "d", "code" : 100 }

MongoDB支持多种条件运算符,包括:

  • $lt (小于)
  • $lte (小于或等于)
  • $gt (大于)
  • $gte (大于或等于)
  • $all (匹配数组中的所有值)
  • $exists (检查字段是否存在)
  • $mod (模数)
  • $ne (不等于)
  • $in (匹配数组中的一个或多个值)
  • $nin (匹配数组中的零值)
  • $or (匹配一个查询或另一个查询)
  • $nor (既不匹配一个查询,也不匹配另一个查询)
  • $size (匹配具有定义数量的元素的任何数组)
  • $type (匹配具有指定BSON数据类型的值)
  • $not (不等于)

有关所有这些运算符的更多详细信息,请参阅MongoDB文档(请参阅参考资料中的链接)。

您可以使用find函数中的第二个参数来限制查询返回的字段。 例如,以下查询将仅返回代码值在102到105范围内的所有文档的char属性: > db.alphabet.find({code:{$in:[102,103,104,105]}}, {char: 1});

这将产生清单13中的结果。

清单13.结果
{ "_id" : ObjectId("4cfa4adf528bad4e29beec91"), "char" : "f" }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec92"), "char" : "g" }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec93"), "char" : "h" }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec94"), "char" : "i" }

在下一节中,您将学习如何创建索引以加快查询速度。

索引编制

MongoDB索引与关系数据库索引非常相似。 您可以在任何属性上放置索引。 另外,索引字段可以是任何数据类型,包括对象或数组。 与RDBMS索引一样,您可以使用多个属性和唯一索引创建复合索引,以确保不允许重复值。

要创建基本索引,请使用ensureIndex函数。 现在,让我们在字母集合中的codechar属性上创建一个索引(请参见清单14 )。

清单14.创建一个索引
> db.alphabet.ensureIndex({code: 1});
> db.alphabet.ensureIndex({char: 1});

您可以使用dropIndex和dropIndexes函数删除索引。 有关更多信息,请参阅MongoDB文档。

排序

要对结果集进行排序,可以将排序功能应用于光标。 我们的字母集合已经在代码和char属性上按升序排序,因此让我们按代码属性按升序返回子集: > db.alphabet.find({code: {$gte: 118}}).sort({code: 0});

这将返回清单15中的结果。

清单15.结果
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca5"), "char" : "z", "code" : 122 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca4"), "char" : "y", "code" : 121 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca3"), "char" : "x", "code" : 120 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca2"), "char" : "w", "code" : 119 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beeca1"), "char" : "v", "code" : 118 }

如果您在上一个命令中将参数{code: 1 }提供给sort函数,它将以升序对结果进行排序。 为确保高性能查询,请确保将索引添加到用于对数据进行排序的任何属性。

使用跳过和限制来分页结果

通常,在处理数据结果集时,您一次只想检索一个子集,也许想在网页上提供分页的结果。 在MySQL中,通常使用LIMIT关键字执行此操作。 您可以使用跳过和限制功能在MongoDB中轻松复制此功能。 要返回字母集合中的前5个文档,可以执行以下操作: > db.alphabet.find().limit(5);

这将返回清单16中的结果。

清单16.结果
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8c"), "char" : "a", "code" : 97 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8d"), "char" : "b", "code" : 98 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8e"), "char" : "c", "code" : 99 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec8f"), "char" : "d", "code" : 100 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec90"), "char" : "e", "code" : 101 }

要获取下一页,请使用以下命令: > db.alphabet.find().skip(5).limit(5);

清单17所示 ,这将获取接下来的5条记录。

清单17.获取下五个记录
{ "_id" : ObjectId("4cfa4adf528bad4e29beec91"), "char" : "f", "code" : 102 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec92"), "char" : "g", "code" : 103 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec93"), "char" : "h", "code" : 104 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec94"), "char" : "i", "code" : 105 }
{ "_id" : ObjectId("4cfa4adf528bad4e29beec95"), "char" : "j", "code" : 106 }

组功能和汇总

MongoDB的查询引擎还使在数据上应用聚合和分组功能变得非常简单。 这些类似于它们SQL副本。 可以说,使用最广泛的函数是count()函数: > db.alphabet.find().count();

这应该返回26。您可以轻松地计算过滤的查询: > db.alphabet.find({code: {$gte: 105}}).count();

上面的语句应返回18。

另一个有用的聚合函数是distinct 。 这用于为属性返回一组不同的值。 我们的字母集合是一个糟糕的例子,因为所有数据都是唯一的,所以让我们在本文前面创建的colors集合中添加几条记录(请参见清单18 )。

清单18.将记录添加到color集合
> db.colors.save({name:"white",value:"FFFFFF"});
> db.colors.save({name:"red",value:"FF0000"});  
> db.colors.find();

假设您没有删除colors集合,那么应该在清单19中看到响应。

清单19.响应
{ "_id" : ObjectId("4cfa43ff528bad4e29beec57"), "name" : "red", "value" : "FF0000" }
{ "_id" : ObjectId("4cfa5830528bad4e29beeca8"), "name" : "white", "value" : "FFFFFF" }
{ "_id" : ObjectId("4cfa5839528bad4e29beeca9"), "name" : "red", "value" : "FF0000" }

如您所见,此集合中显然有两个红色文档。 现在,让我们使用distinct函数从该集合中获取一组唯一的name属性值: > db.colors.distinct("name");

这将返回以下内容: [ "red", "white" ]

值得注意的是,您不会像执行其他查询功能那样在游标或结果集上执行独特功能,而是直接在集合上执行它。 您还将注意到,它不返回一组文档,而是返回一组值。

MongoDB还提供了用于执行操作的group功能,就像在SQL中的GROUP BY表达式中一样。 group功能是一个复杂的野兽,因此在这里我仅举一个简单的例子。 对于我们的示例,假设我们要计算按名称值分组的文档数。 在SQL中,我们可以将此表达式定义为SELECT name, COUNT(*) FROM colors GROUP BY name;

要在MongoDB中执行此查询,您将使用清单20中的命令。

清单20.使用group函数
> db.colors.group(
... {key: {name: true},
... cond: {},
... initial: {count: 0},                                  
... reduce: function(doc, out) { out.count++; }
... });

这将产生清单21中的结果。

清单21.结果
[
    {
        "name" : "red",
        "count" : 2
    },
    {
        "name" : "white",
        "count" : 1
    }
]

如果您需要执行高级聚合或使用大型数据集,则MongoDB还包括map/reduce的实现,这将使您能够这样做。 上面概述的分组功能在分片的MongoDB设置中不起作用,因此,如果您使用分片,请确保使用map/reduce代替。

更新现有数据

在MongoDB Shell中,更新文档非常容易。 在我们先前创建的颜色集合中,我们有两个关于red记录。 假设我们要获取这些记录之一并将其更改为black ,其值属性为000000 (黑色的十六进制值)。 首先,我们可以使用findOne函数检索值为红色的单个项目,根据需要更改其属性,然后将文档保存回数据库。

获得一个名称为red文档并将其存储在blackDoc变量中: > var blackDoc = db.colors.findOne({name: "red"});

接下来,我们使用点符号来更改文档的属性(请参见清单22 )。

清单22.更改文档的属性
> blackDoc.name = "black";
> blackDoc.value = "000000";

保存之前,让我们检查一下文档看起来是否正确(应该具有_id属性,否则它将只插入一条新记录,而不是保存在红色记录上): > printjson(blackDoc);

如果返回类似于清单23的内容 ,就可以开始了。

清单23.结果
{
    "_id" : ObjectId("4cfa43ff528bad4e29beec57"),
    "name" : "black",
    "value" : "000000"
}

最后,使用save功能将文档保存回数据库中的colors集合: > db.colors.save(blackDoc);

现在,我们可以使用find函数来确保我们的集合看起来正确: > db.colors.find();

这应该返回类似于清单24的内容 。 如果您有4条记录,说明您做错了。

清单24.结果
{ "_id" : ObjectId("4cfa43ff528bad4e29beec57"), "name" : "black", "value" : "000000" }
{ "_id" : ObjectId("4cfa5830528bad4e29beeca8"), "name" : "white", "value" : "FFFFFF" }
{ "_id" : ObjectId("4cfa5839528bad4e29beeca9"), "name" : "red", "value" : "FF0000" }

在Mongo Shell之外,您将在应用程序中使用更新功能将更改应用于现有数据。 有关更新功能的更多信息,请参阅MongoDB文档。

删除资料

要删除MongoDB中的数据,请使用remove功能。 请注意,这适用于MongoDB Shell程序,某些驱动程序可能实现删除功能或其他方式。 如果需要,请查阅文档以了解特定的实现。

remove函数的工作方式与find函数类似。 要删除颜色集合中与名称white相匹配的所有文档,可以使用以下命令: > db.colors.remove({name:"white"});

然后,您可以检查该文档是否已删除: > db.colors.find();

如果一切顺利,您应该只会看到两个文档(请参见清单25 )。

清单25.删除数据
{ "_id" : ObjectId("4cfa43ff528bad4e29beec57"), "name" : "black", "value" : "000000" }
{ "_id" : ObjectId("4cfa5839528bad4e29beeca9"), "name" : "red", "value" : "FF0000" }

要删除集合中的所有文档,只需从命令中省略过滤器,如下所示: > db.colors.remove();

现在,当您尝试使用find函数时,将不会得到任何响应,表示结果集为空: > db.colors.find();

如果您有一个存储在变量中的文档,也可以将此文档传递给remove函数以将其删除,但这是一种低效的方式。 您最好找到本文档的_id属性,并将其传递给remove函数。

要删除集合,可以使用以下命令: > db.colors.drop();

这将返回以下内容: true

现在,您可以使用show collections命令检查是否确实删除了该show collections 。 这应该产生清单26中的输出。

清单26.使用show collections命令
alphabet
system.indexes

最后,如果要删除整个数据库,请执行以下命令: > db.dropDatabase();

这将删除当前选择的数据库。 您应该看到以下输出: { "dropped" : "mymongo", "ok" : 1 }

您可以使用命令show dbs获取可用数据库的列表。 mymongo不应出现在此列表中。

工具和其他功能

MongoDB包括一系列有用的实用程序,用于管理数据库。 它提供了用于报告或备份目的的各种数据导入和导出方法。 在本节中,您将发现如何以JSON格式导入和导出文件,以及如何创建更有效的热备份文件以进行恢复。 您还将了解如何使用map/reduce函数替代Mongo常规查询函数来进行复杂的数据聚合。

导入和导出数据

MongoDB的bin目录包含用于以各种格式导入和导出数据的一系列实用程序。 mongoimport实用程序允许您为文件提供每行包含JSON,CSV或TSV格式的文档,并将每个文档插入MongoDB数据库。 由于MongoDB使用BSON,因此,如果要导入JSON文档,则希望使用常规JSON中不可用的BSON的任何其他数据类型,需要提供一些修饰符信息。

mongoexport实用程序允许您使用MongoDB数据库中的每个文档以JSON或CSV格式生成文件输出。 这对于在应用程序接受JSON或CSV数据作为输入的情况下生成报告很有用。 要生成CSV文件,您需要按其在输出文件中出现的顺序提供字段。

备份和还原数据库

mongoimport和mongoexport实用程序对于将数据从MongoDB中取出以用于其他应用程序或从其他可以使JSON或CSV数据可用的应用程序导入有用。 但是,不应将这些实用程序用于定期备份或MongoDB数据库或还原MongoDB数据库。 由于MongoDB使用BSON而不是JSON或CSV,因此从这些格式导入数据时,很难保留数据类型。

为了提供适当的备份和还原功能,MongoDB提供了两个实用程序:mongodump和mongorestore。 mongodump会生成数据库的二进制文件备份,mongorestore会读取该文件并使用该数据库还原数据库,并根据需要自动创建索引(除非您已从备份目录中删除了system.indexes.bson文件)。

管理实用程序

MongoDB还提供了基于Web的诊断界面; 在默认的MongoDB配置上可从http://localhost:28017/获得。 该屏幕类似于图2中的屏幕截图。

图2. MongoDB诊断
MongoDB诊断

要获取其他管理信息,您还可以在MongoDB Shell中运行以下命令:

  • db.serverStatus();
  • db.stats();

如果MongoDB服务器崩溃,则应该修复数据库以检查是否有损坏并执行一些数据压缩。 您可以通过在操作系统命令行上运行mongod --repair或使用db.repairDatabase()命令来进行修复。 从MongoDB shell。 后一个命令在每个数据库级别运行,因此您需要为服务器上的每个数据库运行此命令。

您还可以使用验证功能来验证收集数据。 如果您有一个名为contacts的集合,则可以使用命令db.contacts.validate();来验证该集合db.contacts.validate();

MongoDB具有许多其他功能,可简化DBA的工作。 此外,还有各种第三方管理工具和界面。 有关更多信息,请参阅MongoDB文档。

地图/缩小

如果您以前使用过CouchDB数据库,则您可能对map/reduce很熟悉,因为视图引擎默认使用map/reduce函数来过滤和聚合数据。 在MongoDB中,情况并非如此。 简单的查询和过滤(甚至聚合)不依赖于map/reduce 。 但是,MongoDB确实提供了map/reduce的实现,可用于聚合大型数据集。

map/reduce可能需要自己撰写一篇文章。 有关MongoDB实现的详细信息,请参阅MongoDB文档(请参阅参考资料中的链接)。

扩展MongoDB

密钥/值存储和面向文档的数据库最近流行的主要原因是它们的占用空间小且易于扩展。 In order to facilitate this, MongoDB relies on the concepts of sharding and replication, which you will learn about in this section. In addition, you'll also learn how you can store large files in MongoDB using GridFS. Finally, you'll see how you can profile your queries to optimize the performance of your database.

Sharding

An important part of any database infrastructure is ensuring that it scales well. MongoDB implementations are scaled horizontally using an auto-sharding mechanism, allowing the scaling of a MongoDB configuration to thousands of nodes, with automatic load balancing, no single point of failure and automatic failover. It is also very straightforward to add new machines to a MongoDB cluster.

The beauty of MongoDB's auto-sharding features is that it makes it very straightforward to go from a single server to a sharded cluster, often with little or no changes to application code required. For detailed documentation on how auto-sharding works and how to implement it, see the MongoDB documentation.

Replication

MongoDB provides replication features in a master-slave configuration (similar to MySQL) for the purposes of failover and redundancy, ensuring a high level of consistency between nodes. Alternatively, MongoDB can use replica sets to define a node as a primary at any one time, with another node taking over as the primary in the event of a failure.

Unlike CouchDB, which uses replication as the basis for scaling, MongoDB uses replication primarily for ensuring high availability by using slave nodes as redundant replicas.

For further information on MongoDB replication, see the documentation (see Related topics for a link).

Large file storage with GridFS

MongoDB databases store data in BSON documents. The maximum size of a BSON document is 4MB however, which makes them unsuitable for storing large files and objects. MongoDB uses the GridFS specification to store large files, by dividing the file into smaller chunks among multiple documents.

The standard MongoDB distribution includes command line utilities for adding and retrieving GridFS files to and from the local file system. In addition, all official MongoDB API drivers include support for GridFS. For more details, refer to the MongoDB documentation (see Related topics ).

结论

In this article, you learned about the MongoDB database management system and why it is one of the fastest-growing options in the popular NoSQL section of the DBMS market. You learned about why you would choose a document-oriented database over a traditional RDBMS, and about the various great features that MongoDB has to offer. You learned how to install and use MongoDB for storage and retrieval of data, and about the various tools and scalability options it provides.


翻译自: https://www.ibm.com/developerworks/opensource/library/os-mongodb4/index.html

探索mongodb

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值