热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Node.js系列使用MongoDB数据库

#前言作为还在漫漫前端学习路上的一位自学者。我以学习分享的方式来整理自己对于知识的理解,同时也希望能够给大家作为一份参考。希望能够和大家共同进步,如有任何纰漏的话,希望大家多多指正

# 前言

作为还在漫漫前端学习路上的一位自学者。我以学习分享的方式来整理自己对于知识的理解,同时也希望能够给大家作为一份参考。希望能够和大家共同进步,如有任何纰漏的话,希望大家多多指正。感谢万分!

在这一节让我们开始学着在 Node.js 中使用 MongoDB 数据库.

# 什么是 MongoDB

『 MongoDB 』 是由 C++ 语言编写的, 基于分布式文件存储的数据库. 属于 NoSql (非关系型数据库) 的一种, 旨在为 WEB 应用提供可扩展的高性能数据存储解决方案.

MongoDB 将数据存储为一个文档,数据结构由键值对 key:value 组成. MongoDB 文档类似于 JSON 对象. 字段值可以包含其他文档,数组及文档数组.

下面就是一个 MongoDB 文档 (document) 示例:

{
"name": "Garrik",
"age": 21,
"gender": "Male",
"job": "Frontend Developer"
}

## 关系型数据库 & 非关系型数据库

前面说到 MongoDB 是属于非关系型数据库的一种, 那么什么是关系型? 什么是非关系型?

关系型数据库 』以 “行” 和 “列” 组成的 “二维表格” 形式来存储数据, 二维表格简称为称为表, 表又组成了数据库. 之所以称之为关系型数据库, 因为表与表之间采用了现实世界中实体 (entitiy) 与实体 (entitiy) 之间的关系模型. 表中存储格式化结构的数据,每个 “元组”(可以理解为二维表中的一行)的字段组成都是一样的. 即使不是每个元组都需要所有的字段,但数据库会为每个元组都分配所有的字段,这样的结构可以便于表与表之间进行连接等操作. 比较常见的关系型数据库有 Oracle, MySQL 等.

非关系数据库 』以 “键值对” 存储,它的结构不固定,每一个元组可以有不一样的字段,可以根据需要增加或减少一些自己的键值对,不会局限于固定的结构. 数据之间的关联性不强制, 使用起来要比关系型数据库更加灵活, 性能也有提升. 比较常见的非关系型数据库有 MongoDB, Redis 等

# MongoDB 基础概念

在具体讲如何使用 MongoDB 之前, 我要先介绍一些基本概念.

## 文档 (document)

文档 』是一组 “键值对” 的有序集合. 是 MongoDB 的核心概念. 文档的数据结构被称为 BSON, 是一种类似于 JSON 的二进制形式的存储格式. 下面是一个文档示例:

{
"name": "Garrik",
"age": 21
}

"name""age" 是这个文档的 “键” (key), "Garrik"21 是 “值” (value)

文档中的值可以是多种不同的数据类型. 在一个集合中各个文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型.

MongoDB 区分类型和大小写. 例如,下面的两个文档是不同的:

{"foo" : 3}
{"Foo" : "3"}

在给文档的 “键” 命名时还需要注意: 文档的键必须是字符串 键不能含有 \0 (空字符)。这个字符用来表示键的结尾 .$ 有特别的意义,只有在特定环境下才能使用 以下划线 _开头的键是保留的 (不是严格要求的) * 一个文档内不能有重复的键

## 集合 (collection)

集合 』就是一组文档,如果将 MongoDB 中的一个文档比喻为关系型数据库中的一行,那么一个集合就相当于一张表. 集合存在于数据库中,当第一个文档插入时,集合就会被创建. 集合没有固定的结构,一个集合里面的文档可以是各式各样的,这被称为 『 动态模式 』

下面是一个集合示例:

{
"site": "www.baidu.com",
"name": "百度"
}
{
"site": "www.google.com",
"name": "Google",
"query": {
"search": "前端开发"
}
}
{
"site": "www.zhihu.com",
"name": "知乎",
"username": "罐装汽水_Garrik"
}

虽然 MongoDB 对集合中的文档类型没有要求, 但通常情况下我们插入集合的数据都会有一定的关联性. 这样会降低查询特定文档的复杂度, 并且提升查询速度.

集合命名时需要注意: 集合名不能是空字符串。 集合名不能含有 \0(空字符),这个字符表示集合名的结尾。 集合名不能以 system. 开头,这是为系统集合保留的前缀。 用户创建的集合名字不能含有保留字符 $

## 数据库 (database)

数据库 』由多个集合组成. 在 MongoDB 中可以建立多个数据库。每个数据库都有独立的权限,即便是在磁盘上,不同的数据库也放置在不同的文件中。按照经验,我们将有关一个应用程序的所有数据都存储在同一个数据库中。要想在同一个 MongoDB 服务器上存放多个应用程序或者用户的数据,就需要使用不同的数据库。

MongoDB 的默认数据库为 "db",该数据库存储在 data 目录中。

数据库名可以是满足以下条件的任意 UTF-8 字符串: 不是空字符串 不得含有 空格.$/\\0 (空字符) 数据库名区分大小写, 推荐全部小写 最多 64 字节

数据库最终会变成文件系统里的文件,而数据库名就是相应的文件名

文档, 表单, 数据库之间的关系如下图:

《Node.js 系列 - 使用 MongoDB 数据库》
《Node.js 系列 - 使用 MongoDB 数据库》

# 安装 MongoDB & 可视化工具

这篇文章我不想过多讲安装步骤, 大家可以自行去查阅方法.

Windows 平台安装 MongoDBwww.runoob.com《Node.js 系列 - 使用 MongoDB 数据库》
Mac OSX 平台安装 MongoDBwww.runoob.com《Node.js 系列 - 使用 MongoDB 数据库》

为了更方便的管理 MongoDB 数据库, 我推荐使用 Studio 3T 可视化工具.

The MongoDB GUI, IDE & Client for Professional Devs – Studio 3Tstudio3t.com《Node.js 系列 - 使用 MongoDB 数据库》

使用方法可参照下面链接内容:

MongoDB可视化工具Studio 3T的使用blog.csdn.net《Node.js 系列 - 使用 MongoDB 数据库》

# 在 Node.js 中使用 MongoDB

MongoDB Driver API for Node.jsmongodb.github.io

想要在 Node.js 中使用 MongoDB, 要先安装 mongodb 模块, 具体步骤不赘述. 在 Node.js 中使用之前, 还需要先在命令行中用 mongod 指令运行 MongoDB 服务器.

以下代码适用于 mongodb 模块 3.x 版本

## 连接数据库

要想连接 MongoDB 数据库, 我们要先创建一个 MongoDB 客户端并且连接上 MongoDB 服务器. 之后在此连接之上创建数据库实例.

// 引入模块 const MongoClient = require('mongodb').MongoClient;
// MongoDB 服务器的地址 const url = 'mongodb://localhost:27017';
// 目标数据库的名字 const dbname = 'mydb';
// 创建 MongoDB 客户端 const client = new MongoClient(url);
// 让客户端连接上服务器 client.connect(function(err) {
if (err) throw err;
console.log("成功连接到 MongoDB 服务器!");
// 创建数据库实例 const db = client.db(dbname);
// 断开连接 client.close();
});

## 插入文档

要想向一个特定的集合插入文档, 首先我们用 db.collection 方法去获取目标集合的实例对象. 该方法第一个参数为集合的名字. 如果用这个名字的集合之前不存在, 它会自动帮你创建.

之后我们用刚刚获得的集合实例的 insertManyinsertOne 方法来向集合插入文档.

区别是: insertOne 用以插入单个文档, 第一个参数为文档对象 insertMany 用以插入多个文档, 第一个参数为由文档对象组成的数组

这两个方法的最后一个参数都为回调函数. 回调函数的第一个参数为错误信息, 第二个为处理结果

假如说我们现在要向 usersInfo 集合插入用户信息, 代码如下:

client.connect(function(err) {
if (err) throw err;
const db = client.db(dbname);
// 获取 'usersInfo' 集合的实例对象. const collection = db.collection('usersInfo');
// 插入单个用户的信息 collection.insertOne({
name: "Garrik",
date_of_birth: new Date("1997-06-04")
}, function(err, result) {
if (err) throw err;
client.close();
})
});

## 查询全部文档

如果我们想查询一个集合下的全部文档, 我们可以使用集合实例的 find 方法. 该方法的第一个参数为查询条件对象, 如果传入一个空对象 {} 则表示查询全部文档.

client.connect(function(err) {
if (err) throw err;
const db = client.db(dbname);
// 获取 'usersInfo' 集合的实例对象. const collection = db.collection('usersInfo');
// 查询集合下的所有文档, 然后用 toArray 转换成数组 collection.find({}).toArray(function(err, result) {
if (err) throw err;
console.log(result);
client.close();
});
});

## 查询特定文档

前面说集合实例的 find 方法的第一个参数为查询条件对象. 想要查找特定文档的前提是知道怎么写查询条件对象.

首先, 平时最常用的查询是找到有特定 “键值对” 的文档. 比如找到 “文档中有 name 键, 且它的值为 小明“. 这个查询写成查询条件对象是: {'name':'小明'}. 假如要查询的文档在 usersInfo 集合下, 在 Node.js 的代码就为:

// 客户端连接上服务器 client.connect(function(err) {
if (err) throw err;
console.log("成功连接到 MongoDB 服务器!");
// 创建数据库实例 const db = client.db(dbname);
//查询 'name' 等于 '小明' 的文档 db.collection('usersInfo').find({ 'name': '小明' }).toArray((err, array) => {
if (err) throw err;
// 打印出匹配到的文档 console.log(array);
// 关闭客户端 client.close();
})
});

如果再想加一条 gender 键的值 等于 male. 那查询条件对象就为 {'name':'小明', 'gender':'male'} 查询条件对象中各个条件是 AND 的关系. 也就是只匹配 name 键的值等于 小明, 且 gender 键的值为 male 的文档.

假如集合中的文档有如下:

{ "_id" : ObjectId("5bd1e7df8a5c0550f4722b01"), "name" : "小明", "gender" : "male" }
{ "_id" : ObjectId("5bd1e7e28a5c0550f4722b02"), "name" : "小明", "gender" : "female" }
{ "_id" : ObjectId("5bd1e7e88a5c0550f4722b03"), "name" : "小红", "gender" : "female" }
{ "_id" : ObjectId("5bd1e7f48a5c0550f4722b04"), "name" : "小王", "gender" : "male" }

那么执行上面代码匹配到的为:

{ "_id" : ObjectId("5bd1e7df8a5c0550f4722b01"), "name" : "小明", "gender" : "male" }

## 数值比较

上面的查询条件都是精确匹配, 也就是匹配文档中某个键的值是否等于多少. 平时常用的另一个查询是范围比较. 也就是 <, >, <=, >=, !=. 它们对应的 MongoDB 关键字为 $lt, $gt, $lte, $gte.

比如要匹配 age 键的值小于 60, 那么查询条件对象为 {'age': {$lt:60}}.

如果在小于 60 的同时还要大于 18, 那就是 {'age': {$lt:60, $gt:18}}.

## OR 查询

MongoDB 中有两种方式进行 OR 查询: $in 关键字可以查询一个键的多个值 $or 可以用于多个键值对.

比如我们要查 name 键的值为 小明 或者 小红 的文档. 用 $in 的话, 文档查询对象为 {'name': {$in: ['小明', '小红']}}; 用 $or 的话, 文档查询对象为 {$or:[{'name':'小明'}, {'name':'小红'}]}

但如果我们要查 name 键的值为 小明小红, 或者 gender 键的值为 male 的文档的话, $in$or 结合使用会很方便. 其文档查询对象为 {$or:[{'name':{$in:['小明','小红']}}, {'gender':'male'}]}

## 更新文档

使用集合实例的 updateOneupdateMany 方法可以更新文档. 它们的第一个参数为查询对象, 用来匹配到需要更新的文档. 第二个参数为更新对象, 也就是要应用于文档上的更新内容. 最后一个参数为回调函数, 回调函数第一个参数为错误信息, 第二个为操作结果. 这两个方法的区别是 updateOne 只更新匹配到的第一个文档, updateMany 更新所有匹配到的文档.

比如我们要更新 name 键的值为 小明 的文档的 age 键为 22. Node.js 代码如下: (注意更新对象里面的 $set 关键字)

// 客户端连接上服务器 client.connect(function(err) {
if (err) throw err;
console.log("成功连接到 MongoDB 服务器!");
// 创建数据库实例 const db = client.db(dbname);
//查询 'name' 等于 '小明' 的文档, 然后更新 `age` 键 db.collection('usersInfo').updateOne({ 'name': '小明' }, { $set: { 'age': 22 } }, function(err, result) {
if (err) throw err;
console.log(result);
// 关闭客户端 client.close();
});
});

## 删除文档

想要删除一个文档可以用 deleteOnedeleteMany 方法. 第一参数为查询对象, 最后一个参数为回调函数.

比如我们要删除 name小明 的第一个文档. Node.js 代码如下:

// 客户端连接上服务器 client.connect(function(err) {
if (err) throw err;
console.log("成功连接到 MongoDB 服务器!");
// 创建数据库实例 const db = client.db(dbname);
//删除 'name' 等于 '小明' 的第一条文档 db.collection('usersInfo').deleteOne({ 'name': '小明' }, function(err, result) {
if (err) throw err;
console.log(result);
// 关闭客户端 client.close();
});
});

&#x1f606; 好啦,今天的分享就告一段落啦。在下一期我会手把手演示如何实现一个连接了 MongoDB 数据库的 Todo List 页面程序.

罐装汽水Garrik:Node.js 系列 &#8211; [实战] TODO 单页面程序zhuanlan.zhihu.com《Node.js 系列 - 使用 MongoDB 数据库》

如果喜欢的话就点个关注吧!O(∩_∩)O 谢谢各位的支持&#x2757;&#xfe0f;


推荐阅读
  • 数据库基本介绍
    1、数据库基本知识概念:数据库:database(DB),是一种存储数据的仓库数据库是根据数据结构组织、存储和 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了前端人员必须知道的三个问题,即前端都做哪些事、前端都需要哪些技术,以及前端的发展阶段。初级阶段包括HTML、CSS、JavaScript和jQuery的基础知识。进阶阶段涵盖了面向对象编程、响应式设计、Ajax、HTML5等新兴技术。高级阶段包括架构基础、模块化开发、预编译和前沿规范等内容。此外,还介绍了一些后端服务,如Node.js。 ... [详细]
  • 本文介绍了关系型数据库和NoSQL数据库的概念和特点,列举了主流的关系型数据库和NoSQL数据库,同时描述了它们在新闻、电商抢购信息和微博热点信息等场景中的应用。此外,还提供了MySQL配置文件的相关内容。 ... [详细]
  • 玩转直播系列之消息模块演进(3)
    一、背景即时消息(IM)系统是直播系统重要的组成部分,一个稳定的,有容错的,灵活的,支持高并发的消息模块是影响直播系统用户体验的重要因素。IM长连接服务在直播系统有发挥着举足轻重的 ... [详细]
  • 【转】腾讯分析系统架构解析
    TA(TencentAnalytics,腾讯分析)是一款面向第三方站长的免费网站分析系统,在数据稳定性、及时性方面广受站长好评,其秒级的实时数据更新频率也获得业界的认可。本文将从实 ... [详细]
  • 数据库进入全新时代,腾讯云发布五大数据库提前布局
    8月28日,腾讯云数据库在京正式启动战略升级,宣布未来将聚焦云原生、自治、超融合三大战略方向,以用户为中心,联接未来。并在现场面向全球用户同步发布五大战略级新品,包括数据库智能管家 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • python限制递归次数(python最大公约数递归)
    本文目录一览:1、python为什么要进行递归限制 ... [详细]
  • 一面自我介绍对象相等的判断,equals方法实现。可以简单描述挫折,并说明自己如何克服,最终有哪些收获。职业规划表明自己决心,首先自己不准备继续求学了,必须招工作了。希望去哪 ... [详细]
  • step1.为mongodb添加admin管理员root@12.154.29.163:~#mongoMongoDBshellversionv3.4.2connectingto:mo ... [详细]
  • SeMITechnologies正在使用矢量搜索引擎Weaviate构建的内容。SeMI的首席执行官兼联合创始人BobvanLuijt说,它是一种独特的AI优先数据库,使用机器学习 ... [详细]
  • 我这几年踩过的十个坑,每一条都是血泪教训
    “阅读本文大概需要3分钟。”一、不记录程序部署在哪里“我:他妈的,这个程序明明一直在正确产生日志,可它到底运行在哪里?怎么我 ... [详细]
author-avatar
_陈灵宝互粉号2
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有