MongoDB 數據庫概述及環境搭建


1 數據庫概述及環境搭建

1.1 為什么要使用數據庫

動態網站中的數據都是存儲在數據庫中的
數據庫可以用來持久存儲客戶端通過表單收集的用戶信息
數據庫軟件本身可以對數據進行高效的管理

1.2 什么是數據庫

數據庫即存儲數據的倉庫,可以將數據進行有序的分門別類的存儲。它是獨立於語言之外的軟件,可以通過 API 去操作它。

常見的數據庫軟件有:mysql、mongoDB、oracle

1.3 MongoDB 數據庫下載安裝

下載地址:https://www.mongodb.com/download-center/community

還要下載 MongoDB Compass 圖形界面軟件,下載地址:https://www.mongodb.com/download-center/compass

在安裝過程中,Custom 自定義安裝可以選擇安裝路徑,以后都選擇默認安裝就可以了。

相關概念:

一個網站有多個網站應用,所以一個數據庫有多個 database(庫)

一個網站應用有多種類數據,比如用戶信息、商品信息,所以之下有 collection(類)

一類數據小有多條數據,所以之下有 document(條)

一條數據下有多種屬性,所以之下有 field(屬性)

1.4 MongoDB 可視化軟件

MongoDB 可視化操作軟件,是使用圖形界面操作數據庫的一種方式。

MongoDB Compass 可以在安裝 MongoDB 的時候安裝,也可以單獨安裝。

1.5 數據庫相關概念

在一個數據庫軟件中可以包含多個數據倉庫,在每個數據倉庫中可以包含多個數據集合,每個數據集合中可以包含多條文檔(具體的數據)。

1.6 Mongoose 第三方包

使用 Node.js 操作 MongoDB 數據庫需要依賴 Node.js 第三方包 mongoose

它下面的 connect 方法可以連接數據庫。

使用 npm install mongoose 命令下載

創建項目 database ,並在命令行工具切換到 database 目錄下,進行安裝,輸入:

npm install mongoose

1.7 啟動 MongoDB 

在命令行工具中運行 net start mongoDB ,即可啟動MongoDB,否則MongoDB將無法鏈接。

在命令行工具中,停止MongoDB,輸入:

net stop MongoDB

啟動MongoDB,輸入:

net start mongoDB

1.8 數據庫鏈接

使用 mongoDB 提供的 connect 方法即可連接數據庫

基本語法:

mongoose.connect('mongodb://localhost/playground')
  .then(() => console.log('數據庫連接成功'))
  .catch(err => console.log('數據庫連接失敗',err));

例子:

新建 01.js 文件,先引入 mongoose:

const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/playground')
  .then(() => console.log('數據庫連接成功'))
  .catch((err) => console.log(err,'數據庫連接失敗'))

回到命令行工具,輸入:

node 01.js

結果是:

可以看到數據庫連接成功,但是在之前有一些 mongoose 的提示,說是:當前的 current URL 解析器,已經被廢棄掉了,在將來的版本中將會被刪除掉,然后讓你使用新的解析器。{ useNewUrlParser: true, useUnifiedTopology: true }

修改下代碼:

// 引入mongoose 第三方模塊,用來操作數據庫
const mongoose = require('mongoose');
// 數據庫連接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true, useUnifiedTopology: true })
  // 連接成功
  .then(() => console.log('數據庫連接成功'))
  // 連接失敗
  .catch((err) => console.log(err,'數據庫連接失敗'));

在命令行工具中重新運行,結果:

1.9 創建數據庫

在 MongoDB 中不需要顯示創建數據庫,如果正在使用的數據庫不存在,MongoDB 會自動創建

2 MongoDB 增刪改查操作

2.1 創建集合

創建集合分為兩步:一是對集合設置規則,二是使用規則創建集合。創建 mongoose.Schema 構造函數的實例即可創建集合。 

語法:

// 設定集合規則
const courseSchema = new mongoose.Schema({
  name: String,
  author: String,
  isPublished: Boolean
});
// 創建集合並應用規則
const Course = mongoose.model('Course', courseSchema); // courses

mongoose.model 創建集合,第一個參數是集合的名稱,集合名稱的首字母應該大寫,比如:Course,當實際上 mongoose 在數據庫中創建的集合名稱是:courses,是小寫,后面加 s 代碼復數,因為是集合。Course 接收的是 mongoose.model 的返回值:構造函數。

例子:新建 02.js 文件:

// 引入mongoose 第三方模塊,用來操作數據庫
const mongoose = require('mongoose');
// 數據庫連接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true, useUnifiedTopology: true })
  // 連接成功
  .then(() => console.log('數據庫連接成功'))
  // 連接失敗
  .catch((err) => console.log(err,'數據庫連接失敗'));

// 設定集合規則
const courseSchema = new mongoose.Schema({
  name: String,
  author: String,
  isPublished: Boolean
});
// 使用規章創建集合
const Course = mongoose.model('Course', courseSchema); // courses

回到命令行工具,輸入:

node 02.js

提示:數據庫連接成功。

然后打開 MongoDBCompass 軟件,刷新后並沒有看到我們寫的 playground 數據庫,是因為沒有為集合插入數據,所以就沒有創建數據庫。下面我們需要插入一條數據。

2.2 創建文檔

創建文檔實際上就是向集合中插入數據

分為兩步:

1)創建集合實例

2)調用實例對象下的 save 方法,將數據保存到數據庫中

基礎語法:

// 創建集合實例
const course = new Course({
  name: 'Node.js course',
  author: 'joe',
  tags: ['node', 'backend'],
  isPublished: true
});
// 將數據保存到數據庫中
course.save();

繼續編輯 02.js 文件:

// 引入mongoose 第三方模塊,用來操作數據庫
const mongoose = require('mongoose');
// 數據庫連接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true, useUnifiedTopology: true })
  // 連接成功
  .then(() => console.log('數據庫連接成功'))
  // 連接失敗
  .catch((err) => console.log(err,'數據庫連接失敗'));

// 設定集合規則
const courseSchema = new mongoose.Schema({
  name: String,
  author: String,
  isPublished: Boolean
});
// 使用規章創建集合
const Course = mongoose.model('Course', courseSchema); // courses
// 創建集合實例
const course = new Course({
  name: 'Node.js 基礎',
  author: 'joe',
  isPublished: true
});
// 將數據保存到數據庫中
course.save();

回到命令行工具中,重新運行,輸入:

node 02.js

然后打開  MongoDBCompass 軟件,刷新后就可以看到 playground 數據庫了

 

點擊 courses 集合,可以看到里面有一條數據。

 

_id 屬性段是當前數據的唯一標識,是數據庫自動生成的。

還有一種方式可以向集合中插入文檔。

語法:

Course.create({name: 'Node.js 基礎', author: 'joe', isPublished: true}, (err, doc) => {
  // 錯誤對象
  console.log(err)
  // 當前插入的文檔
  console.log(doc)
});

例子:

新建 03.js 文件:

// 引入mongoose 第三方模塊,用來操作數據庫
const mongoose = require('mongoose');
// 數據庫連接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true, useUnifiedTopology: true })
  // 連接成功
  .then(() => console.log('數據庫連接成功'))
  // 連接失敗
  .catch((err) => console.log(err,'數據庫連接失敗'));

// 設定集合規則
const courseSchema = new mongoose.Schema({
  name: String,
  author: String,
  isPublished: Boolean
});
// 使用規章創建集合
// 第1個參數代表集合名稱
// 第2個參數代表集合規則
const Course = mongoose.model('Course', courseSchema); // courses
// 向集合中插入文檔
Course.create({name: 'JavaScript', author: 'joe', isPublished: false}, (err, result) => {
  // 錯誤對象
  console.log(err)
  // 當前插入的文檔
  console.log(result)
});

回到命令行工具,輸入:

node 03.js

結果:

 

第1個參數 null 代表:插入是成功的;第2個參數是插入文檔的那一條數據。

回到 MongoDBCompass 軟件,點擊刷新,可以看到有2條數據了:

關於數據庫的所有操作,都是異步操作。

mongoose 當中提供的 API 也支持 promise 的方式:

Course.create({name: 'JavaScript 基礎', author: 'joe', isPublished: true})
  .then(doc => console.log(doc))
  .catch(err => console.log(err))

例子:修改下 03.js 文件:

// 引入mongoose 第三方模塊,用來操作數據庫
const mongoose = require('mongoose');
// 數據庫連接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true, useUnifiedTopology: true })
  // 連接成功
  .then(() => console.log('數據庫連接成功'))
  // 連接失敗
  .catch((err) => console.log(err,'數據庫連接失敗'));

// 設定集合規則
const courseSchema = new mongoose.Schema({
  name: String,
  author: String,
  isPublished: Boolean
});
// 使用規章創建集合
// 第1個參數代表集合名稱
// 第2個參數代表集合規則
const Course = mongoose.model('Course', courseSchema); // courses

// 向集合中插入文檔
// Course.create({name: 'JavaScript', author: 'joe', isPublished: false}, (err, result) => {
//   // 錯誤對象
//   console.log(err)
//   // 當前插入的文檔
//   console.log(result)
// });

Course.create({name: 'JavaScript123', author: 'joe', isPublished: false})
  .then(result => {
    console.log(result)
  })
  .catch(err => {
    console.log(err)
  })

回到命令行工具中重新運行 03.js

結果:

回到 MongoDBCompass 軟件,點擊刷新,可以看到有3條數據了。

總結:可以通過 create 方法來向集合中插入數據,它有兩種接收異步 API 的方式:第一種通過回調函數的方式,第二種通過 promise 對象的方式。 

2.3 mongoDB 數據庫導入數據

把現成的數據插入到數據庫中,需要用 到mongoDB 提供的命令:mongoimport

mongoimport -d 數據庫名稱 -c 集合名稱 --file 要導入的數據文件

在命令行工具中輸入:mongoimport,提示無法識別,並沒有找到 mongoimport 的可執行文件,我們需要手動將命令的所在的目錄添加到系統環境變量 path 中去,命令行工具才能找到 mongoimport 命令的可執行文件。命令的所在目錄就是mongoDB 數據庫的安裝目錄。

打開本地電腦的 mongoDB 安裝目錄,在里面找到 bin目錄,打開可以看到 mongoimport.exe 文件,並復制它的目錄:

把復制好的目錄添加到系統的環境變量 path 中:

 

保存后,需要把命令行工具進行重啟,記得重啟好后,要切換到 database 目錄下。

然后將准備好的 user.json 文件中的數據,導入到數據庫中。在命令行輸入:

mongoimport -d playground -c users --file ./user.json

結果:表示找到了本機當做的數據庫,導入了6個文檔。

 

然后打開 Compass 軟件,點擊刷新,可以看到新增加了一個 users 集合,里面有6條數據:

 

2.4 查詢文件

語法:

// 根據條件查找文檔(條件為空則查找所有文檔)
Course.find().then(result => console.log(result))

find() 返回的是:文檔集合。

例子:

新建 04.js 文件:

// 引入mongoose第三方模塊 用來操作數據庫
const mongoose = require('mongoose');
// 數據庫連接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
    // 連接成功
    .then(() => console.log('數據庫連接成功'))
    // 連接失敗
    .catch(err => console.log(err, '數據庫連接失敗'));

// 創建集合規則
const userSchema = new mongoose.Schema({
    name: String,
    age: Number,
    email: String,
    password: String,
    hobbies: [String]
});

// 使用規則創建集合
const User = mongoose.model('User', userSchema);

// 查詢用戶集合中的所有文檔
User.find().then(result => console.log(result));

切換到命令行工具,輸入:

node 04.js

可以看到結果:返回的是一個數組,數組里包含了多個對象。

 

可以在 find() 方法里傳遞一個對象,那么這個對象就是查詢條件。

例如:查詢用戶 id 為多少的,在 Compass 里,隨便復制一個 id 值,修改下 04.js 文件:

// 使用規則創建集合
const User = mongoose.model('User', userSchema);

// 查詢用戶集合中的所有文檔
// User.find().then(result => console.log(result));
// 通過_id字段查找文檔
User.find({_id: '5c09f1e5aeb04b22f8460965'}).then(result => console.log(result))

在命令行工具中輸入:node 04.js

可以看到查詢結果:

可以看到返回的還是一個數組,里面有一條數據。

總結:通過 find() 方法查詢出的數據,無論有多少,它返回的都是一個數組。如果查找的數據不存在,那么會返回一個空數組。

另外一個方法 findOne:

語法:

// 根據條件查找文檔
Course.findOne({name: 'node.js 基礎'}).then(result => console.log(result))
findOne方法返回一個對象。如果不加查詢條件,那么返回的是當前集合中的第一條數據。

例子:繼續編輯04.js 文件:

// 查詢用戶集合中的所有文檔
// User.find().then(result => console.log(result));
// 通過_id字段查找文檔
// User.find({_id: '5c09f1e5aeb04b22f8460965'}).then(result => console.log(result))

// findOne方法返回一條文檔 默認返回當前集合中的第一條文檔
User.findOne().then(result => console.log(result))

回到命令工具,輸入:node 04.js

結果:返回的是一個對象(第一條數據文檔)

例子:查詢名字是“李四”的數據:

User.findOne({name: '李四'}).then(result => console.log(result))

匹配大於$gt  小於$lt:

語法:

// 匹配大於 小於
User.find({age: {$gt: 20, $lt: 50}}).then(result => console.log(result))

例子:04.js 文件:

// 查詢用戶集合中年齡字段大於20並且小於40的文檔
User.find({age: {$gt: 20, $lt: 40}}).then(result => console.log(result))

命令行工具中,輸入:node 04.js

結果:

匹配包含 $in:

語法:

// 匹配包含
User.find({hobbies: {$in: ['足球']}}).then(result => console.log(result))

例子:

// 查詢用戶集合中hobbies字段值包含足球的文檔
User.find({hobbies: {$in: ['足球']}}).then(result => console.log(result))

結果是:

選擇要查詢的字段 select:

// 選擇要查詢的字段
User.find().select('name email').then(result => console.log(result))

例子:

// 選擇要查詢的字段 名字和郵件地址
User.find().select('name email').then(result => console.log(result))

結果:

可以看到 _id 是默認字段,自動查詢出來的。如果不想查詢出 _id 字段,寫作:-_id

例子:

// 選擇要查詢的字段
User.find().select('name email -_id').then(result => console.log(result))

結果:

對查詢出來的數據進行排序 sort

語法:

// 將數據按照年齡進行排序
User.find().sort('age').then(result => console.log(result))

例子:根據年齡字段進行升序排列

// 根據年齡字段進行升序排列
User.find().sort('age').then(result => console.log(result))

// 根據年齡字段進行降序排列
User.find().sort('-age').then(result => console.log(result))

跳過數據skip 和 限制查詢數量limit

語法:

// skip 跳過多少條數據 limit 限制查詢數量
User.find().skip(2).limit(3).then(result => console.log(result))

例子:

// 查詢文檔跳過前兩條結果 限制顯示3條結果
User.find().skip(2).limit(3).then(result => console.log(result))

2.5 刪除文檔

刪除單個文檔:

// 刪除單個
Course.findOneAndDelete({}).then(result => console.log(result))

如果查詢條件包含了多條文檔,那么會將第一個匹配的文檔刪除。返回值是刪除的這條文檔。

例子:新建 05.js 文件:

// 引入mongoose第三方模塊 用來操作數據庫
const mongoose = require('mongoose');
// 數據庫連接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
    // 連接成功
    .then(() => console.log('數據庫連接成功'))
    // 連接失敗
    .catch(err => console.log(err, '數據庫連接失敗'));

// 創建集合規則
const userSchema = new mongoose.Schema({
    name: String,
    age: Number,
    email: String,
    password: String,
    hobbies: [String]
});

// 使用規則創建集合
const User = mongoose.model('User', userSchema);

// 查找到一條文檔並且刪除
// 返回刪除的文檔
// 如何查詢條件匹配了多個文檔 那么將會刪除第一個匹配的文檔
User.findOneAndDelete({_id: '5c09f267aeb04b22f8460968'}).then(result => console.log(result))

在命令行工具,輸入:

node 05.js

返回一條文檔,也就是被刪除的這條數據。

然后打開 Compass 軟件,刷新后可以看到只剩下5條數據了,‘王五’的那條數據被刪除了。

刪除多個文檔:

// 刪除多個
User.deleteMany({}).then(result => console.log(result))

依然返回 promise 對象。

例子:05.js 文件:

// 刪除多條文檔,如果查詢條件為空對象,那么會把數據庫中 User 集合中的所有文檔都刪除
User.deleteMany({}).then(result => console.log(result))

回到命令行工具,輸入:node 05.js

結果:

然后打開 Compass 軟件,刷新后可以看到 users 這個集合里是空的了。

2.6 更新文檔

更新單個文檔:

// 更新單個文檔
User.updateOne({查詢條件}, {要修改的值}).then(result => console.log(result))

如果有多個查詢結果,會更新第一條文檔。

例子:

因為我們上面把users集合里的數據都刪除了,下面要重新導入下 user.json 文件中的數據,在命令行工具中輸入:

mongoimport -d playground -c users --file ./user.json

然后新建 06.js 文件:

// 引入mongoose第三方模塊 用來操作數據庫
const mongoose = require('mongoose');
// 數據庫連接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
    // 連接成功
    .then(() => console.log('數據庫連接成功'))
    // 連接失敗
    .catch(err => console.log(err, '數據庫連接失敗'));

// 創建集合規則
const userSchema = new mongoose.Schema({
    name: String,
    age: Number,
    email: String,
    password: String,
    hobbies: [String]
});

// 使用規則創建集合
const User = mongoose.model('User', userSchema);
// 更新集合中的單個文檔
User.updateOne({name: '李四'}, {age: 120, name: '李狗蛋'}).then(result => console.log(result))

在命令行工具輸入:

node 06.js

結果:

打開 Compass 軟件,刷新后可以看到 users 這個集合中的“李四”,變為了“李狗蛋”,年齡改為了120。

更新多個文檔:

// 更新多個文檔
User.updateMany({查詢條件}, {要更改的值}).then(result => console.log(result))

查詢條件為空的話,表示更新所有文檔。

例子:修改 06.js 文件:

// 更新集合中的單個文檔
// User.updateOne({name: '李四'}, {age: 120, name: '李狗蛋'}).then(result => console.log(result))

// 更新集合中的多個文檔
User.updateMany({}, {age: 56}).then(result => console.log(result))

在命令行工具中輸入:

node 06.js

然后結果可以看到所有文檔的年齡都改為了 56。

2.6 mongoose 驗證 

在創建集合規則時,可以設置當前字段的驗證規則,驗證失敗則輸入插入失敗。

● required.true 必傳字段

例子:新建 07.js 文件:

// 引入mongoose第三方模塊 用來操作數據庫
const mongoose = require('mongoose');
// 數據庫連接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
    // 連接成功
    .then(() => console.log('數據庫連接成功'))
    // 連接失敗
    .catch(err => console.log(err, '數據庫連接失敗'));

const postSchema = new mongoose.Schema({
  title: {
    type: String,
    required: true
  }
});

// 使用規則創建集合
const Post = mongoose.model('Post', postSchema);

Post.create({}).then(result => console.log(result))

在命令行工具輸入:node 07.js,會提示錯誤信息。

因為設置 title 字段為必傳字段,但是插入文檔的時候為空對象,所以會提示錯誤。

如果把 required: true 去掉,在重新運行 07.js,即使插入空對象,也會提示插入成功。然后打開 Compass 軟件,會發現多了一個 posts 集合。

如果想自定義報錯信息的話,可以修改設置為:

title: {
    type: String,
    required: [true, '請傳入文章標題']
  }

第一個參數 true 為必傳,第二個參數就是自定義的錯誤信息。

在命令行工具中重新輸入:node 07.js

結果的自定義錯誤信息:

● minlength 最小長度

● maxlength 最大長度

title: {
    type: String,
    required: [true, '請傳入文章標題'],
    minlength: 2,
    maxlength: 5
  }

例子:

const postSchema = new mongoose.Schema({
  title: {
    type: String,
    required: [true, '請傳入文章標題'],
    minlength: 2,
    maxlength: 5
  }
});

// 使用規則創建集合
const Post = mongoose.model('Post', postSchema);

Post.create({title: 'a'}).then(result => console.log(result))

運行后會提示:

Post validation failed: title: Path `title` (`a`) is shorter than the minimum allowed length (2).

在修改代碼為 title: 'aaaaaa' 

運行后會提示:

Post validation failed: title: Path `title` (`aaaaaa`) is longer than the maximum allowed length (5).

當然 minlength 和 maxlength 也可以自定義錯誤信息,格式同 required 一樣:

minlength: [2, '文章標題長度不能小於2'],
maxlength: [5, '文章標題長度最大不能超過5']

● trim: true 去除字符串兩端空格

例子:

// 引入mongoose第三方模塊 用來操作數據庫
const mongoose = require('mongoose');
// 數據庫連接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true}) // 連接成功 .then(() => console.log('數據庫連接成功')) // 連接失敗 .catch(err => console.log(err, '數據庫連接失敗')); const postSchema = new mongoose.Schema({ title: { type: String, required: [true, '請傳入文章標題'], minlength: [2, '文章標題長度不能小於2'], maxlength: [5, '文章標題長度最大不能超過5'], trim: true } }); // 使用規則創建集合 const Post = mongoose.model('Post', postSchema); Post.create({title: ' aaa '}).then(result => console.log(result))

在命令行工具中輸入: node 07.js

結果:可以看到兩端的空格沒有了,標題就是:aaa

● min: 2 數值最小為2

● max: 100 數值最大為100

例子: 修改 07.js 文件

// 引入mongoose第三方模塊 用來操作數據庫
const mongoose = require('mongoose');
// 數據庫連接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true}) // 連接成功 .then(() => console.log('數據庫連接成功')) // 連接失敗 .catch(err => console.log(err, '數據庫連接失敗')); const postSchema = new mongoose.Schema({ title: { type: String, // 必選字段 required: [true, '請傳入文章標題'], // 字符串的最小長度 minlength: [2, '文章標題長度不能小於2'], // 字符串的最大長度 maxlength: [5, '文章標題長度最大不能超過5'], // 去除字符串兩邊的空格 trim: true }, age: { type: Number, min: 18, max: 100 } }); // 使用規則創建集合 const Post = mongoose.model('Post', postSchema); Post.create({title: 'aa', age: 10}).then(result => console.log(result))

運行后結果提示報錯:

Post validation failed: age: Path `age` (10) is less than minimum allowed value (18).

當然如果想自定義錯誤信息,格式和上面是一樣的。

● default 默認值

例子:修改 07.js

// 引入mongoose第三方模塊 用來操作數據庫
const mongoose = require('mongoose');
// 數據庫連接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
    // 連接成功
    .then(() => console.log('數據庫連接成功'))
    // 連接失敗
    .catch(err => console.log(err, '數據庫連接失敗'));

const postSchema = new mongoose.Schema({
  title: {
    type: String,
    // 必選字段
    required: [true, '請傳入文章標題'],
    // 字符串的最小長度
    minlength: [2, '文章標題長度不能小於2'],
    // 字符串的最大長度
    maxlength: [5, '文章標題長度最大不能超過5'],
    // 去除字符串兩邊的空格
    trim: true
  },
  age: {
    type: Number,
    min: 18,
    max: 100
  },
  publishDate: {
    type: Date,
    // 默認值
    default: Date.now
  }
});

// 使用規則創建集合
const Post = mongoose.model('Post', postSchema);

Post.create({title: 'aa', age: 60}).then(result => console.log(result))

在命令行工具中輸入:node 07.js

結果:

回到 Compass 軟件,發現 posts 集合多了一條文檔:

● enum: ["html", "css", "javascript", "node.js"]  枚舉,列舉出當前字段可以擁有的值(只能傳固定的一些值)

例子:修改 07.js

// 引入mongoose第三方模塊 用來操作數據庫
const mongoose = require('mongoose');
// 數據庫連接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
    // 連接成功
    .then(() => console.log('數據庫連接成功'))
    // 連接失敗
    .catch(err => console.log(err, '數據庫連接失敗'));

const postSchema = new mongoose.Schema({
  title: {
    type: String,
    // 必選字段
    required: [true, '請傳入文章標題'],
    // 字符串的最小長度
    minlength: [2, '文章標題長度不能小於2'],
    // 字符串的最大長度
    maxlength: [5, '文章標題長度最大不能超過5'],
    // 去除字符串兩邊的空格
    trim: true
  },
  age: {
    type: Number,
    // 數字的最小范圍
    min: 18,
    // 數字的最大范圍
    max: 100
  },
  publishDate: {
    type: Date,
    // 默認值
    default: Date.now
  },
  category: {
    type: String,
    // 枚舉 列舉出當前字段可以擁有的值
    enum: ['html', 'css', 'javascript', 'node.js']
  }
});

// 使用規則創建集合
const Post = mongoose.model('Post', postSchema);

Post.create({title: 'aa', age: 60, category:'java'}).then(result => console.log(result))

結果:提示報錯信息

Post validation failed: category: `java` is not a valid enum value for path `category`.

把代碼中的類型修改為:html

Post.create({title: 'aa', age: 60, category:'html'}).then(result => console.log(result))

就可以運行插入成功了。

● validate:自定義驗證器,mongoose 提供了自定義驗證規則

例子:修改 07.js

// 引入mongoose第三方模塊 用來操作數據庫
const mongoose = require('mongoose');
// 數據庫連接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
    // 連接成功
    .then(() => console.log('數據庫連接成功'))
    // 連接失敗
    .catch(err => console.log(err, '數據庫連接失敗'));

const postSchema = new mongoose.Schema({
  title: {
    type: String,
    // 必選字段
    required: [true, '請傳入文章標題'],
    // 字符串的最小長度
    minlength: [2, '文章標題長度不能小於2'],
    // 字符串的最大長度
    maxlength: [5, '文章標題長度最大不能超過5'],
    // 去除字符串兩邊的空格
    trim: true
  },
  age: {
    type: Number,
    // 數字的最小范圍
    min: 18,
    // 數字的最大范圍
    max: 100
  },
  publishDate: {
    type: Date,
    // 默認值
    default: Date.now
  },
  category: {
    type: String,
    // 枚舉 列舉出當前字段可以擁有的值
    enum: ['html', 'css', 'javascript', 'node.js']
  },
  author: {
    type: String,
    validate: {
      validator: v => {
        // 返回一個布爾值
        // true 表示驗證成功;false 表示驗證失敗
        // v 表示要驗證的值
        return v && v.length > 4
      },
      // 自定義錯誤信息
      message: '傳入的值不符合驗證規則'
    }
  }
});

// 使用規則創建集合
const Post = mongoose.model('Post', postSchema);

Post.create({title: 'aa', age: 60, category:'html', author: 'bd'}).then(result => console.log(result))

運行后結果:

Post validation failed: author: 傳入的值不符合驗證規則

create 方法返回的是 promise 對象,可以通過 .then() 方法拿到插入成功的返回值,所以我們也可以通過 .catch() 方法拿到插入失敗的失敗對象。
修改下 07.js 代碼:
Post.create({title: 'aa', age: 60, category:'html', author: 'bd'})
  .then(result => console.log(result))
  .catch(error => console.log(error))

重新運行:node 07.js

結果:author 字段插入的值不符合規章

如果插入文檔中有多個字段不符合規則:

Post.create({title: 'aa', age: 60, category:'java', author: 'bd'})
  .then(result => console.log(result))
  .catch(error => console.log(error))

運行后的結果:category 字段和 author 字段插入的值都不符合規章

 

可以看到第一層是 errors,然后里面有 category 對象和 author 對象,再里面的 message 字段為錯誤信息。

那么我們就可以把 .cacth 里面寫一個遍歷數組,把錯誤信息都輸出出來:

Post.create({title: 'aa', age: 60, category:'java', author: 'bd'})
  .then(result => console.log(result))
  .catch(error => {
    // 獲取錯誤信息對象
    const err = error.errors
    // 循環錯誤信息對象
    for(var i in err) {
      console.log(err[i].message);
      // console.log(err[i]['message']);
    }
  })

重新運行后可以看到結果:

下面我們把第一個錯誤信息也自定義下:

category: {
    type: String,
    // 枚舉 列舉出當前字段可以擁有的值
    enum: {
      values: ['html', 'css', 'javascript', 'node.js'],
      message: '分類名稱要在一定的范圍內才可以'
    }
  },

重新運行后的結果:

3.7 集合關聯

通常不同集合的數據之間是有關系的,例如文章信息和用戶信息存儲在不同的集合中,但文章是某個用戶發表的,要查詢文章的所有信息包括發表用戶,就需要用到集合關聯。

● 使用 id 對集合進行關聯

● 使用 populate 方法進行關聯集合查詢

語法:

// 用戶集合
const User = mongoose.model('User', new mongoose.Schema({ name: { type: String} }));
// 文章集合
const Post = mongoose.model('Post', new mongoose.Schema({
  title: { type: String },
  // 使用 id 將文章集合和用戶集合進行關聯
  author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
}));

// 聯合查詢
Post.find()
  .populate('author')
  .then((err, result) => console.log(result));
ObjectId  就是  _id

例子:新建 08.js 文件:

// 引入mongoose第三方模塊 用來操作數據庫
const mongoose = require('mongoose');
// 數據庫連接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
    // 連接成功
    .then(() => console.log('數據庫連接成功'))
    // 連接失敗
    .catch(err => console.log(err, '數據庫連接失敗'));

// 用戶集合規則
const userSchema = new mongoose.Schema({
    name: {
        type: String,
        required: true
    }
});
// 文章集合規則
const postSchema = new mongoose.Schema({
    title: {
        type: String
    },
    // 使用 id 將文章集合和用戶集合進行關聯
  author: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User' 
  }
});
// 用戶集合
const User = mongoose.model('User', userSchema);
// 文章集合
const Post = mongoose.model('Post', postSchema);

// 創建用戶
User.create({name: 'joe'}).then(result => console.log(result));

在命令行工具中,輸入:

node 08.js

結果:創建用戶成功

回到 Compass 軟件中,刷新可以看到:創建的用戶 joe

然后進行創建文章:

// 創建用戶
// User.create({name: 'joe'}).then(result => console.log(result));
// 創建文章 author 值為用戶的 id
Post.create({titile: '123', author: '5eb9057561a07b1680de2a21'}).then(result => console.log(result));

運行后可以看到結果:

回到 Compass 軟件中,刷新可以看到:創建的文章

然后進行查詢:

// 創建用戶
// User.create({name: 'joe'}).then(result => console.log(result));
// 創建文章 author 值為用戶的 id
// Post.create({title: '123', author: '5eb9057561a07b1680de2a21'}).then(result => console.log(result));
// 聯合查詢
Post.find().populate('author').then(result => console.log(result))

重新運行后結果:

2.8 案例:用戶信息增刪改查 

1、搭建網站服務器:實現客戶端與服務端的通信
2、連接數據庫,創建用戶集合,向集合中插入文檔
3、當用戶訪問 /list 時,將所有用戶信息查詢出來
4、將用戶信息和表格 HTML 進行拼接,並將拼接結果響應回客戶端
5、當用戶訪問 /add 時,呈現表單頁面,並實現添加用戶信息功能
6、當用戶訪問 /modify 時,呈現修改頁面,並實現修改用戶信息功能
7、當 用戶訪問 /delete 時,實現刪除用戶功能

具體代碼:

https://www.cnblogs.com/joe235/p/12869891.html 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM