当前位置:首页 > 编程语言 > 正文内容

什么是MongoDB?关于这个流行的开源数据库的所有信息

a811625533年前 (2022-10-09)编程语言28

本教程向你介绍了MongoDB数据库。你将发现如何安装该软件、操作数据,并将数据设计技术应用于你自己的应用程序。

所有的例子都是使用MongoDB 5开发的,但大多数都可以在以前或以后的版本中使用。代码可以直接输入到客户端应用程序或MongoDB shell(mongo或mongosh),以查询和更新数据库

什么是MongoDB?

MongoDB是一个。NoSQL意味着该数据库不像那样使用关系表。

有一系列的NoSQL数据库类型,但MongoDB将数据存储在被称为文档的类似JavaScript的对象中,其内容看起来像这样:

{
_id: "123",
name: "CrAIg"
}

虽然MongoDB已经成为基于JavaScript的框架的代名词,但大多数框架、语言和运行时都有MongoDB官方,包括、。你也可以选择像Mongoose这样的库,提供更高层次的抽象或对象关系映射(ORM)功能。

与SQL表不同,你可以在MongoDB中存储的内容没有结构限制。数据模式不被强制执行。你可以在你喜欢的地方存储任何你喜欢的东西。这使得MongoDB成为更多有机的–或混乱的–数据结构的理想选择。

考虑一个联系地址簿。个人往往有多个 *** 号码。你可以在一个SQL表中定义三个 *** 字段,但这对一些联系人来说太多,对另一些人来说太少。最终,你将需要一个单独的 *** 表,这就增加了复杂性。

在MongoDB中,这些 *** 号码可以被定义为同一个文档中无限的对象阵列。

{
_id: "123",
name: "Craig",
telephone: [
{ home: "0123456789" },
{ work: "9876543210" },
{ cell: "3141592654" }
]
}

请注意,MongoDB使用类似的JavaScript对象符号进行数据更新和查询,如果你习惯于SQL,这可能会带来一些挑战。

MongoDB的要素

在我们进一步讨论之前,让我们看一下MongoDB的特点。我们将在本文中使用这些词汇。

  • Document。数据存储中的一个单独的对象,类似于SQL数据库表中的记录或行。
  • Field。文件中的一个单一数据项,如姓名或 *** 号码,类似于SQL字段或表列。
  • Collection。一组类似的文件,类似于一个SQL表。虽然你可以把所有的文件放到一个 *** 中,但通常把它们分成特定的类型更实用。在一个联系人地址簿中,你可以有一个人的 *** 和一个公司的 *** 。
  • Database。一个相关数据的 *** ,与SQL数据库的含义相同。模式。一个模式定义了数据
  • Schema。在SQL数据库中,你必须在存储数据之前定义带有相关字段和类型的表定义。这在MongoDB中是没有必要的,尽管它可以创建一个模式,在文件被添加到 *** 之前对其进行验证。
  • Index。一种用于提高查询性能的数据结构,与SQL索引的含义相同。
  • Primary Key。每个文档的唯一标识符。MongoDB会自动为 *** 中的每个文档添加一个唯一的、有索引的_id字段。
  • Denormalization。在SQL数据库中,”规范化 “是一种用于组织数据和消除重复的技术。在MongoDB中,鼓励 “去规范化”。你积极地重复数据,一个单一的文件可以包含所有需要的信息。
  • JOINs。SQL提供了一个JOIN操作符,因此可以在一次查询中从多个规范化的表中检索数据。在MongoDB中,直到3.6版本才可以进行连接,而且限制仍然存在。这也是为什么数据应该被反规范化为自包含文件的另一个原因。
  • Transactions。当一个更新改变了一个文档上的两个或更多的值时,MongoDB确保它们全部成
    功或全部失败。跨越两个或多个文档的更新必须被包裹在一个事务中。MongoDB从4.0
    版本开始支持交易,但需要一个多服务器副本集或分片集群。下面的安装示例使用的是
    单台服务器,因此不可能有事务。

如何安装MongoDB

在你的本地机器上使用MongoDB,你有三种选择。我们将引导你了解每个选项。

1. 使用docker(推荐)。

是一个软件管理工具,可以在几分钟内安装、配置和运行MongoDB或任何其他应用程序。

,然后创建一个项目文件夹,其中有一个名为dockercompose.yml的文件,包含以下内容(注意,缩略号是必不可少的)。

version: '3'
services:
mongodb:
image: mongo:5
environment:
- MONGO_INITDB_ROOT_USERNAME=root
- MONGO_INITDB_ROOT_PASSWORD=pass
- MONGO_INITDB_DATABASE=mongodemo
container_name: mongodb
volumes:
- dbdata:/data/db
ports:
- "27017:27017"
adminer:
image: dehy/adminer
container_name: adminer
depends_on:
- mongodb
ports:
- "8080:80"
volumes:
dbdata:

从命令行访问该文件夹并运行。

docker-compose up

最新版本的MongoDB 5将被下载并启动。这在之一次启动时需要几分钟的时间,但随后的运行会快很多。

请注意:

  • 一个MongoDB管理员账户被定义为ID “root “和密码 “pass”。
  • 数据在重启之间被保存在一个名为dbdata的Docker卷中。
  • 还提供了数据库客户端。

您可以使用任何MongoDB数据库客户端,使用ID “root “和密码 “pass “连接到localhost:27017。或者,你可以访问Adminer,网址是http://localhost:8080/,用以下凭证登录。

  • System: MongoDB (alpha)
  • Server: host.docker.internal
  • Username: root
  • Password: pass

信息

服务器host.docker.internal可以在运行Docker Desktop的Mac和windows设备上工作。Linux用户应该使用设备的 *** IP地址,而不是localhost(Adminer将其解析为自己的Docker容器)。

 

Adminer登陆

Adminer允许你检查 *** 和文件。然而,要注意的是, *** 被称为 “表”。

Adminer *** 视图

要运行命令,你可以使用MongoDB Shell (mongosh) 或传统的 mongo 命令行REPL(读取评估打印循环)环境。

访问Docker MongoDB容器的bash shell。

docker exec -it mongodb bash

然后用ID和密码启动MongoDB shell:

mongosh -u root -p pass

(如果你愿意,可以使用传统的 mongo 命令。)然后你可以发布

MongoDB的命令,比如下面这些。

  • show dbs; — – 显示所有数据库
  • use mongodemo; — 使用一个特定的数据库
  • show collections; — 列出数据库中的 ***
  • db.person.find(); — 列出一个 *** 中的所有文档
  • exit; — 退出/关闭shell

通过在项目目录下运行以下命令关闭MongoDB:

docker-compose down

2. 使用云供应商(无需安装)。

你可以使用一个托管的MongoDB实例,所以不需要在本地安装任何东西。互联网连接是必不可少的,响应速度将取决于主机和你的带宽。大多数服务将收取每月和/或兆字节的使用费。

主机通常会提供详细信息,因此你可以使用MongoDB客户端软件远程管理数据库

3. 在本地安装MongoDB

MongoDB可以在Linux、windows或Mac OS上安装和配置。有两个版本可供选择:

  1. 一个商业的企业版
  2. 一个开源的社区版(在本教程中使用)。

提供了各种操作系统的说明。一般来说:

  • Linux版本使用软件包管理器进行安装,上的apt

请务必仔细按照说明进行操作,这样你的安装才会成功!

如何访问你的MongoDB数据库

现在你的MongoDB数据库已经安装完毕,现在是时候学习如何管理它了。让我们讨论一下,为了访问和使用你的数据库,你需要做什么。

1. 安装一个MongoDB客户端

管理数据库需要一个MongoDB客户端应用程序。如果你使用的是云端或本地安装,我们建议你。

是一个基于Web的数据库客户端,它支持MongoDB,尽管目前它仅限于检查 *** 。Adminer可作为一个单一的PHP脚本下载,但如果你使用,它就已经设置好了。

GUI客户端应用程序为更新和检查数据提供了一个更好的界面。有几种选择,包括免费和跨平台的:

MongoDB Compass

,另一个GUI竞争者,提供了一个商业应用程序,免费授予有限的功能。

Studio 3T

你可以通过使用以下任何一种工具来访问你的MongoDB数据库。

  1. 机器 *** 名称、URL或IP地址(本地安装的是localhost)。
  2. MongoDB的端口(默认为27017)。
  3. 一个用户ID和一个password。一个根用户通常是在安装时定义的。

2. 设置和保存数据库访问凭证

根管理员对所有数据库都有不受限制的访问权。一般来说,你应该使用一个具有特定权限的自定义用户来限制访问并。

例如,以下命令创建了一个名为myuser的用户,其密码为mypass,他对mydb数据库有读和写的权限。

use mydb;
db.createUser({
user: "myuser",
pwd: "mypass",
roles: [
{ role: "readWrite", db: "mydb" }
]
});

如何在MongoDB中插入新文件

在插入你的之一个文档之前,不需要定义一个数据库或 *** 。使用任何MongoDB客户端,简单地切换到一个名为mongodemo的数据库:

use mongodemo;

然后在一个新的人员 *** 中插入一个单一的文件:

db.person.insertOne(
{
name: 'Abdul',
company: 'Alpha Inc',
telephone: [
{ home: '0123456789' },
{ work: '9876543210' }
]
}
);

通过运行查询来查看文件,以返回人物 *** 的所有结果:

db.person.find({});

其结果将是这样的:

{
"_id" : ObjectId("62442429854636a03f6b8534"),
name: 'Abdul',
company: 'Alpha Inc',
telephone: [
{ home: '0123456789' },
{ work: '9876543210' }
]
}

如何插入多个文件

你可以通过向传递一个数组来向一个 *** 中插入多个文档。下面的代码创建了额外的人物文档和一个新的公司 *** :

db.person.insertMany([
{
name: 'Brian',
company: 'Beta Inc'
},
{
name: 'Claire',
company: 'Gamma Inc',
telephone: [
{ cell: '3141592654' }
]
},
{
name: 'Dawn',
company: 'Alpha Inc'
},
{
name: 'Esther',
company: 'Beta Inc',
telephone: [
{ home: '001122334455' }
]
},
{
name: 'george',
company: 'Gamma Inc'
},
{
name: 'Henry',
company: 'Alpha Inc',
telephone: [
{ work: '012301230123' },
{ cell: '161803398875' }
]
},
]);
db.company.insertMany([
{
name: 'Alpha Inc',
base: 'US'
},
{
name: 'Beta Inc',
base: 'US'
},
{
name: 'Gamma Inc',
base: 'GB'
},
]);

_id从何而来?

MongoDB自动为 *** 中的每个文档分配一个_id。这是一个ObjectID- 一个BSON(二进制Javascript对象符号)值,其中包含:

  • 创建时的Unix epoch(秒)(4个字节)
  • Aa 5个字节的机器/进程ID
  • 一个3字节的计数器,从一个随机值开始

这是该文档的主键。这个24个字符的十六进制值在数据库中的所有文档中保证是唯一的,而且一旦插入就不能改变。

MongoDB还提供了一个,因此你可以获得文档的创建日期/时间,而不需要明确设置一个值。另外,你可以在创建文档时定义你自己独特的_id值。

数据去规范化

上面插入的记录将每个用户的公司设置为一个字符串,如 “Alpha Inc”。在规范化的SQL数据库中不建议这样做:

  • 这很容易出错:一个用户被分配到 “阿尔法公司”,而另一个则是 “阿尔法公司”(附加句号字符)。他们被视为不同的公司。
  • 更新一个公司名称可能意味着更新许多记录。

SQL的解决方案是创建一个公司表,并使用其主键(可能是一个整数)将一个公司与一个人联系起来。无论公司名称如何变化,主键都会保持不变,数据库可以执行规则以保证数据的完整性。

在MongoDB中鼓励去规范化。你应该积极地重复数据,一个单一的文件可以包含它所需要的所有信息。这有几个优点:

  • 文件是自成一体的,更容易阅读–不需要参考其他文集。
  • 写入性能可以比SQL数据库快,因为执行的数据完整性规则较少。
  • 分片–或将数据分布在多台机器上–变得更容易,因为不需要引用其他 *** 中的数据。

简单的MongoDB查询

你可以通过使用一个空的find()来列出一个 *** 中的所有文档,比如person。

db.person.find({})

返回文档的数量(在我们的例子中,这个数字将是7)。

db.person.find({}).count();

按你喜欢的任何顺序返回文件,如按姓名的反字母顺序。

db.person.find({}).sort({ name: -1 });

你也可以限制返回的文件数量,例如,找到前三个名字:

db.person.find({}).sort({ name: 1 }).limit(2);

你可以通过定义一个或多个字段的查询来搜索特定的记录,例如,定位所有名字被设置为 “Claire”的人的文件。

db.person.find({ name: 'Claire' });

也支持,如$and、$or、$not、$gt(大于)、$lt(小于)和$ne(不等于),例如,定位所有公司为 “Alpha Inc “或 “Beta Inc “的个人文件。

db.person.find({
$or: [
{ company: 'Alpha Inc' },
{ company: 'Beta Inc' }
]
});

在这个例子的数据库中,同样的结果可以用$nin(不在)来提取所有公司不是 “Gamma Inc “的文档。

db.person.find({
company: { $nin: ['Gamma Inc'] }
});

find() *** 中的第二个值对象设置了一个投影,该投影定义了返回的字段。在这个例子中,只有名字被返回(注意,除非明确关闭,否则文档_id总是被返回)。

db.person.find(
{ name:'Claire' },
{ _id:0, name:1 }
);

其结果是:

{
"name" : "Claire"
}

通过,可以找到一个数组中的项目,比如 *** 数组中有工作项目的所有文件。同样的$elemMatch可以在投影中使用,只显示工作编号:

db.person.find(
{
telephone: { $elemMatch: { work: { $exists: true }} }
},
{
_id: 0,
name:1,
telephone: { $elemMatch: { work: { $exists: true }}}
}
);

其结果是:

{
"name" : "Abdul",
"telephone" : [
{ "work" : "9876543210" }
]
},
{
"name" : "Henry",
"telephone" : [
{ "work" : "012301230123" }
]
}

在MongoDB中使用游标

大多数数据库驱动程序允许将查询结果以数组或类似的数据结构形式返回。然而,如果该 *** 包含成千上万的文件,这可能导致内存问题。

像大多数SQL数据库一样,MongoDB支持标的概念。游标允许应用程序在进入下一个项目或放弃搜索之前一次读取查询结果。

游标也可以从MongoDB shell中使用。

let myCursor = db.person.find( {} );
while ( myCursor.hasNext() ) {
print(tojson( myCursor.next() ));
}

如何在MongoDB中创建索引

这个人名 *** 目前有7个文件,所以任何查询都不会有计算成本。然而,想象一下你有一百万个有姓名和电子邮件地址的联系人。联系人可能是按姓名排序的,但电子邮件地址会在一个似乎是随机顺序。

如果你需要通过电子邮件查找一个联系人,数据库将不得不搜索多达一百万个项目才能找到匹配。在电子邮件字段上添加索引可以创建一个查找 “表”,其中电子邮件按字母顺序存储。数据库现在可以使用更有效的搜索算法来定位正确的人。

随着文档数量的增加,索引变得至关重要。一般来说,你应该对任何可能在查询中被引用的字段应用一个索引。你可以对每个字段都应用索引,但要注意这将减慢数据更新的速度,并增加所需的磁盘空间,因为重新编制索引成为必要。

MongoDB提供了一系列的索引类型。

单一字段索引

大多数索引将应用于单个字段,例如,以升序字母顺序对姓名字段进行索引:

db.person.createIndex({ name: 1 });

使用-1会颠倒顺序。这在我们的例子中没有什么好处,但如果你有一个日期字段,最近的事件优先,这可能很实用。

在例子mongodemo数据库中,还有三个索引是有用的:

db.person.createIndex( { company: 1 } );
db.company.createIndex( { name: 1 } );
db.company.createIndex( { base: 1 } );

多个字段的复合索引

在一个索引中可以指定两个或多个字段,例如

db.person.createIndex( { name: 1, company: 1 } );

当一个字段在搜索查询中经常与另一个字段一起使用时,这可能是有用的。

阵列或对象元素的多键索引

文件可能很复杂,往往需要对结构中更深的字段进行索引,如工作 *** :

db.products.createIndex( { 'telephone.work': 1 } );

通配符索引

通配符可以对文档中的每一个字段进行索引。这在较小和较简单的文件上通常是实用的,这些文件可以用各种方式进行查询:

db.company.createIndex( { '$**': 1 } );

全文索引

文本索引允许你创建类似搜索引擎的查询,可以检查所有字符串字段的文本并按相关性排序。你可以将文本索引限制在特定字段:

db.person.createIndex( { name: "text", company: "text" } );

…或者在所有字符串字段上创建一个文本索引:

db.person.createIndex( { "$**": "text" } );

允许你搜索这个索引,比如找到所有引用 “Gamma “的文件:

db.person.find({ $text: { $search: 'Gamma' } });

请注意,全文搜索一般需要五个或更多的字符才能返回有用的结果。

其他指数类型

MongoDB提供了其他几种专门的索引类型:

  • — 二维平面上的点
  • — 类地球体上的几何图形

如何管理MongoDB的索引

在一个 *** 上定义的索引可以用以下 *** 检查:

db.person.getIndexes();

这将返回一个数组的结果,如:

[
{
"v" : 2.0,
"key" : { "_id" : 1.0 },
"name" : "_id_"
},
{
"v" : 2.0,
"key" : { "company" : 1.0 },
"name" : "company_1"
},
{
"v" : 2.0,
"key" : { "name" : 1.0 },
"name" : "name_1"
}
]

key “定义了字段和顺序,而 “name “是该索引的唯一标识符–例如 “company_1 “是公司字段的索引。

索引的有效性可以通过给任何查询添加一个来检查,例如:

db.person.find({ name:'Claire' }).explain();

这将返回一个大的数据集,但 “winningPlan “对象显示了查询中使用的 “indexName”:

"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : { "name" : 1.0 },
"indexName" : "name_1",
}
}

如果有必要,你可以通过引用一个索引的名称来放弃它:

db.person.dropIndex( 'name_1' );

或使用索引规范文件:

db.person.dropIndex({ name: 1 });

.允许你在一条命令中放弃一个以上的索引。

使用MongoDB的数据验证模式

与SQL不同,数据定义模式在MongoDB中是不需要的。你可以在任何时候向任何 *** 中的任何文档发布任何数据。

这提供了相当大的自由。然而,有时你可能要坚持遵守规则。例如,除非一个文件包含一个名字,否则就不可能将其插入到人的 *** 中。

验证规则可以使用来指定,该对象定义了一个所需项目的数组和每个验证字段的属性。人的 *** 已经被创建,但是你仍然可以定义一个模式,指定一个名字字符串是必须的:

db.runCommand({
collMod: 'person',
validator: {
$jsonSchema: {
required: [ 'name' ],
properties: {
name: {
bsonType: 'string',
description: 'name string required'
}
}
}
}
});

试着插入一个没有名字的人的文件:

db.person.insertOne({ company: 'Alpha Inc' });

…命令就会失败:

{
"index" : 0.0,
"code" : 121.0,
"errmsg" : "Document failed validation",
"op" : {
"_id" : ObjectId("624591771658cd08f8290401"),
"company" : "Alpha Inc"
}
}

如果你在使用一个 *** 之前,也可以定义模式。下面的命令实现了与上述相同的规则。

db.createCollection('person', {
validator: {
$jsonSchema: {
required: [ 'name' ],
properties: {
name: {
bsonType: 'string',
description: 'name string required'
}
}
}
}
});

这个更复杂的例子创建了一个用户 *** ,验证了必须提供姓名、电子邮件地址和至少一个 *** 号码:

db.createCollection('users', {
validator: {
$jsonSchema: {
required: [ 'name', 'email', 'telephone' ],
properties: {
name: {
bsonType: 'string',
description: 'name string required'
},
email: {
bsonType: 'string',
pattern: '^.+\@.+$',
description: 'valid email required'
},
telephone: {
bsonType: 'array',
minItems: 1,
description: 'at least one telephone number required'
}
}
}
}
});

如何更新MongoDB中的现有文件

MongoDB提供了几种,包括 updateOne()updateMany()replaceone()。这些都是通过。

  • 一个过滤器对象,用于定位要更新的文件
  • 一个更新对象–或一个更新对象的数组–描述要改变的数据 一个可选的选项对象。
  • 最有用的属性是upsert,它可以在没有发现的情况下插入一个新的文档。

下面的例子更新了姓名被设置为 “Henry “的人的文件。它删除了工作 *** ,增加了家庭 *** ,并设置了一个新的出生日期。

db.person.updateOne(
{ name: 'Henry' },
[
{ $unset: [ 'telephone.work' ] },
{ $set: {
'birthdate': new ISODate('1980-01-01'),
'telephone': [ { 'home': '789789789' } ]
} }
]
);

接下来的例子更新了姓名被设置为 “Ian “的人名文档。这个名字目前并不存在,但将upsert设置为 “true “就可以创建它。

db.person.updateOne(
{ name: 'Ian' },
{ $set: { company: 'Beta Inc' } },
{ upsert: true }
);

你可以在任何时候运行查询命令来检查数据更新。

如何删除MongoDB中的文件

上面的更新例子使用$unset从名字为 “Henry “的文档中删除工作 *** 。要删除整个文档,你可以使用几个中的一个,包括deleteOne()deleteMany()remove()(可以删除一个或多个)。

为Ian新创建的文件可以用适当的过滤器删除。

db.person.deleteOne({ name: 'Ian' });

在MongoDB中使用聚合操作

是强大的,但可能难以理解。它定义了一个系列–或管道- 在一个数组中的操作。该管道的每个阶段都会,如过滤、分组、计算或修改一组文档。一个阶段也可以使用类似SQL JOIN的。得到的文件被传递给管道的下一个阶段,以便在必要时进行进一步处理。

聚合更好用一个例子来说明。我们将逐步建立一个查询,返回在美国某机构工作的人的姓名、公司和工作 *** (如果有的话)。

之一个操作是运行一个$match来过滤美国的公司。

db.company.aggregate([
{ $match: { base: 'US' } }
]);

这样的返回:

{
"_id" : ObjectId("62442429854636a03f6b853b"),
"name" : "Alpha Inc",
"base" : "US"
}
{
"_id" : ObjectId("62442429854636a03f6b853c"),
"name" : "Beta Inc",
"base" : "US"
}

然后我们可以添加一个新的$lookup管道操作符,将公司名称(localField)与人(from) *** 中的公司(foreignField)进行匹配。输出结果将作为一个雇员数组附加到每个公司的文件中:

db.company.aggregate([
{ $match: { base: 'US' } },
{ $lookup: {
from: 'person',
localField: 'name',
foreignField: 'company',
as: 'employee'
}
}
]);

结果是这样的:

{
"_id" : ObjectId("62442429854636a03f6b853b"),
"name" : "Alpha Inc",
"base" : "US",
"employee" : [
{
"_id" : ObjectId("62442429854636a03f6b8534"),
"name" : "Abdul",
"company" : "Alpha Inc",
"telephone" : [
{ "home" : "0123456789" },
{ "work" : "9876543210" }
]
},
{
"_id" : ObjectId("62442429854636a03f6b8537"),
"name" : "Dawn",
"company" : "Alpha Inc"
},
{
"_id" : ObjectId("62442429854636a03f6b853a"),
"name" : "Henry",
"company" : "Alpha Inc",
"telephone" : [
{ "home" : "789789789" }
],
}
]
}
{
"_id" : ObjectId("62442429854636a03f6b853c"),
"name" : "Beta Inc",
"base" : "US",
"employee" : [
{
"_id" : ObjectId("62442429854636a03f6b8535"),
"name" : "Brian",
"company" : "Beta Inc"
},
{
"_id" : ObjectId("62442429854636a03f6b8538"),
"name" : "Esther",
"company" : "Beta Inc",
"telephone" : [
{ "home" : "001122334455" }
]
}
]
}

现在,一个可以删除所有的,但雇员数组除外。随后的可以破坏数组,获得独立的雇员文件。

db.company.aggregate([
{ $match: { base: 'US' } },
{ $lookup: { from: 'person', localField: 'name', foreignField: 'company', as: 'employee' } },
{ $project: { _id: 0, employee: 1 } },
{ $unwind: '$employee' }
]);

其结果是:

{
"employee" : {
"_id" : ObjectId("62442429854636a03f6b8534"),
"name" : "Abdul",
"company" : "Alpha Inc",
"telephone" : [
{ "home" : "0123456789" },
{ "work" : "9876543210" }
]
}
}
{
"employee" : {
"_id" : ObjectId("62442429854636a03f6b8537"),
"name" : "Dawn",
"company" : "Alpha Inc"
}
}
{
"employee" : {
"_id" : ObjectId("62442429854636a03f6b853a"),
"name" : "Henry",
"company" : "Alpha Inc",
"telephone" : [
{ "home" : "789789789" }
]
}
}
{
"employee" : {
"_id" : ObjectId("62442429854636a03f6b8535"),
"name" : "Brian",
"company" : "Beta Inc"
}
}
{
"employee" : {
"_id" : ObjectId("62442429854636a03f6b8538"),
"name" : "Esther",
"company" : "Beta Inc",
"telephone" : [
{ "home" : "001122334455" }
]
}
}

最后,被用来格式化每个文件,所以只返回个人的名字、公司和工作 *** 。接下来是一个$sort操作,以升序的名字顺序输出文件。完整的聚合查询:

db.company.aggregate([
{ $match: { base: 'US' } },
{ $lookup: { from: 'person', localField: 'name', foreignField: 'company', as: 'employee' } },
{ $project: { _id: 0, employee: 1 } },
{ $unwind: '$employee' },
{ $replaceRoot: {
newRoot: {
$mergeObjects: [ {
name: "$employee.name",
company: '$employee.company',
work: { $first: '$employee.telephone.work' }
}, "$name" ]
} } },
{ $sort: { name: 1 } }
]);

其结果是:

{
"name" : "Abdul",
"company" : "Alpha Inc",
"work" : "9876543210"
}
{
"name" : "Brian",
"company" : "Beta Inc",
}
{
"name" : "Dawn",
"company" : "Alpha Inc",
}
{
"name" : "Esther",
"company" : "Beta Inc"
}
{
"name" : "Henry",
"company" : "Alpha Inc"
}

还有其他 *** 可以实现这一结果,但关键是MongoDB可以完成大部分的工作。很少有必要在你的应用程序代码中直接读取文档和操作数据。

如何运行批量MongoDB操作

默认情况下,MongoDB可以处理1,000个并发操作。在使用mongosh时,这不太可能是一个问题,但如果应用程序对单个记录进行一系列的数据操作,就会达到这个限制。Node.js应用程序尤其有问题,因为它们可以迅速发出一系列异步请求,而不必等到它们完成。

为了规避这个问题,MongoDB提供了一个,它接受任何数量的更新,这些更新可以按顺序或按任何顺序执行。

这里有一个Node.js的伪代码例子。

// reference the mycollection collection
const bulk = db.collection('mycollection').initializeUnorderedBulkOp();
// make any number of data changes
bulk.insertOne(...);
bulk.insertMany(...)
bulk.updateOne(...);
bulk.deleteOne(...);
// etc...
bulk.execute();

最后一条语句有效地发出了一个MongoDB请求,所以你有较少的机会达到1000个操作的限制。

小结

MongoDB为内容管理系统、地址簿和社交 *** 等应用提供了一个灵活的存储,在这些应用中,严格的数据结构过于僵硬,难以定义。数据写入速度快,在多个服务器上分片变得更容易。

使用MongoDB数据库编写应用程序也可以是一种解放。它可以在任何时候将任何数据存储在任何文档的 *** 中。当你使用敏捷 *** 学开发一个原型或最小可行产品时,这一点尤其实用,因为需求会随着时间的推移而变化。

也就是说,复杂的查询可能是一个挑战,当你从SQL世界迁移过来的时候,反规范化的概念很难接受。

MongoDB不太适合有严格交易要求的应用程序,因为数据的完整性是至关重要的,例如银行会计和库存控制系统。这些有可识别的数据字段,应在开始编码前设计好。

在这两个极端之间有很多应用类型,所以选择一个合适的数据库变得更加困难。幸运的是,包括MongoDB在内的NoSQL数据库已经开始采用类似SQL的选项,包括JOIN和事务。

相反,SQL数据库,如MySQL和PostgreSQL现在提供类似NoSQL的 *** ON数据字段。他们也可能值得你注意,但像往常一样,最终的选择权在你手中。

扫描二维码推送至手机访问。

版权声明:本文由2345好导航站长资讯发布,如需转载请注明出处。

本文链接:http://www.2345hao.cn/blog/index.php/post/7916.html

分享给朋友:

“什么是MongoDB?关于这个流行的开源数据库的所有信息” 的相关文章

宝塔面板教程之主界面管理篇

宝塔面板教程之主界面管理篇

本章节主要是对宝塔面板的主界面的各个版本进行一个简单的说明。 宝塔面板主界面主要包括:服务器操作系统、服务器状态、站点信息、软件管理及网络流量几个部分。 Windows面板有部分功能未实现,其余部分与Linux面板同步。 系统操作...

宝塔面板教程之文件管理篇

宝塔面板教程之文件管理篇

宝塔面板其中一个最为便捷的功能之一,无需SFTP或者FTP即可对服务器的文件内容进行上传、下载、编辑及删除等管理操作。 文件管理,用于管理该服务器上的文件内容。 文件的基础操作 文件的基础操作有哪些了,主要有这些方面:复制、粘贴、剪切、删除、重命名、压缩、刷新、新建文件、新建目录。...

15种最佳编程字体以帮助您更愉悦地敲代码

15种最佳编程字体以帮助您更愉悦地敲代码

经过几个小时的努力工作后,您是否感到眼睛疲劳或难以阅读代码?许多程序员在开始头疼之前从没想过要切换字体。 如果您经常发现在尝试扫描一千行代码时眼睛模糊不清,或者在停止编码数小时后头疼,那么可能是时候尝试一种新字体了。即使您没有遇到这些症状,设计良好的字体通常也比默认系统字体具有更好的可读性。...

Serverless PHP简介:主要功能、用例以及如何在Lambda上开始使用Bref

Serverless PHP简介:主要功能、用例以及如何在Lambda上开始使用Bref

无服务器计算是一种基于云的执行模型,可以将应用程序作为服务托管,而无需维护服务器。 服务提供商维护服务器上的资源分配,并根据实际使用情况向用户收费。焦点转移到一个人正在创建的核心应用程序上,基础设施完全由服务提供商处理。无服务器计算也称为功能即服务 (FaaS)。 换句话说,Serverle...

揭开Laravel面纱:用于构建Web应用程序的跨平台PHP框架

揭开Laravel面纱:用于构建Web应用程序的跨平台PHP框架

近年来,Web应用程序和网站的开发变得越来越简单。即使是我们当中最受技术挑战的人也已经相当熟练地使用WordPress和Wix等产品。 对于更高级的开发人员,有许多工具可以帮助简化开发过程。这些工具中最有用的工具之一是Laravel。 本文回答了“什么是Laravel?”这个问题。通过将其分...

PostgreSQL与SQL Server之间的16个关键差异

PostgreSQL与SQL Server之间的16个关键差异

市场上有各种各样的数据库可供选择,用户通常可以仔细考虑PostgreSQL与SQL Server,以便为他们的用例找出更好的选择。使用PostgreSQL进行运营的组织可能希望切换到像Microsoft SQL Server这样的数据库,因为它主要迎合不同的数据仓库解决方案、电子商务和其他业务线...