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))
例子:繼續編輯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: 傳入的值不符合驗證規則
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));
例子:新建 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 時,實現刪除用戶功能
具體代碼: