mogoose 創建資料庫並增刪改查
下載
npm i mongoose -s
連接資料庫
const mongoose = require("mongoose");
mongoose.connect(dbURL);
const db = mongoose.connection;
db.on("error", () => {
console.log("鏈接失敗");
});
db.on("open", () => {
console.log("鏈接成功");
});
創建表結構Schema
Schema相當於MySql的表結構
通過定義Schema
來約束數據的類型,支援以下類型數據
類型 | 作用 |
---|---|
String | 定義字元串 |
Number | 定義數字 |
Date | 定義日期 |
Buffer | 定義二進位 |
Boolean | 定義布爾值 |
Mixed | 定義混合類型 |
ObjectId | 定義對象ID |
Array | 定義數組 |
Decimal128 | |
Map |
約束能用對象的方法描述數據類型 是否必須 是否重複 默認值 等,如下定義了一個用戶表結構
注意:如果定義表結構時沒有定義
_id
,mongoose會自己添加一個該欄位,該欄位不會重複,類型為ObjectId
,通過findById()
查詢
const userSachem = new mongoose.Schema(
{
name: {
type: String,
required: true, //! 必須
},
email: {
type: String,
required: true,
unique: true, //! 不重複
},
passWord: {
type: String,
required: true,
},
avatar: {
type: String,
default: null, //! 默認值
},
bio: String, //! 默認沒有可以不寫
},
{
timestamps: true, //! 添加`createdAt updatedAt`創建時間和更新時間兩個欄位
}
);
如果在定義了結構後需要添加新欄位,在實例上使用add()
方法
創建表model
通過mongoose.model(name,sechem)
來創建表結構構造器,通過傳入數據來實例化構造器獲得具體的表
注意:在這一步的時候資料庫已經有了表,表名全是小寫且表明為name加上s,如這裡會創建表
users
const User = mongoose.model("User", userSechem);
通過上面的操作就獲得了表的構造函數,接下來就可以向裡面進行增刪改查了
增
有三種方法在表內增加數據:
通過實例化數據:
- 創建表數據
實例化model
通過傳入具體的數據來實例化表,能獲得一條具體的表數據,類型為Mongoose Documents
,向資料庫中查找到的也是這種類型數據
const user = new User(userData);
- 保存
save
獲得具體的表後只需要調用Model.prototype.save
就會把數據存入資料庫中 注意:該方法為非同步方法
await user.save();
通過Model.create
方法:
通過表構造器的靜態方法create
自動在表中插入新的數據
該方法可以接收多個插入數據,最後的回調函數參數根據數據量決定
該方法支援兩種調用:
- 錯誤優先的回調
- async await
const users = await User.create(
{ name: "1", email: "[email protected]", passWord: "123" },
{ name: "2", email: "[email protected]", passWord: "456" },
{ name: "3", email: "[email protected]", passWord: "789" }
);
res.status(200).json(users); // users是數組
// 或者
User.create(
{ name: "str", email: "[email protected]", passWord: "159" },
{ name: "1", email: "[email protected]", passWord: "123" },
{ name: "2", email: "[email protected]", passWord: "456" },
{ name: "3", email: "[email protected]", passWord: "789" },
(err, doc1, doc2, doc3) => {
if (err) {
return err;
}
res.status(200).json({ doc1, doc2, doc3 });
}
);
通過Model.insertMany
方法
該方法與create
的區別是它接收的第一個參數是數據組成的數組,多條數據只會插入第一條
const user = await User.insertMany({ name: "1", email: "[email protected]", passWord: "123" });
const users = await User.insertMany([
{ name: "2", email: "[email protected]", passWord: "456" },
{ name: "3", email: "[email protected]", passWord: "789" },
]);
查
查找數據
通過Model.find
方法
不傳入參數會查找該表的所有數據
該方法返回值始終是數組
第一個參數
指定數據的某個鍵進行查找,鍵也能是正則表達式
const data = await User.find({ name: /\d/ });
限制查找範圍,通過內置的欄位限制某個欄位的範圍,$where
函數參數來指定查詢的限制範圍
const data = await User.find({
name: { $gt: 1 },
$where: () => this.passWord == parseInt(this.email),
}); // 查找name大於1且密碼和郵箱一樣的
還能通過$and $or $not
等參數來決定查找的範圍
const data = await User.find({
$or: [{ $and: [{ name: /[1,2]/ }, { email: /(@qq.com)$/ }] }, { name: /\w+/ }],
}); // 查找 name為1或2且為QQ郵箱 或 name為字元串 的數據
如果查找的是對象中的屬性用字元串做鍵或者嵌套查找
注意 嵌套查找必須順序一致
// 查找這條數據 { name: "4", email: "[email protected]", passWord: "357", bio: { head: 123, foot: 789 } }
const datas = await User.find({ "bio.head": 123 }); // 字元串查找
const datas = await User.find({ bio: { head: 123, foot: 456 } }); // 嵌套對象查找 對象要寫全且順序不能改變,裡面只能用具體的數據,不能用正則表達式或其它的限制
如果查找的是數組中的某項
// 有這兩條數據 { name: "4", email: "[email protected]", passWord: "357", bio: [123, 456, "hahaha"] }
// { name: "5", email: "[email protected]", passWord: "258", bio: [123, 789, "haha"] }
const datas = await User.find({ bio: 123 }); // 如果數組中有一個數據符合就會找到 也能像上面一樣用特殊參數指定範圍
const datas = await User.find({ bio: { $all: [123, 456] } }); // 查找含有這兩個值 只能找到第二條
const datas = await User.find({ bio: { $in: [456, 789] } }); // 查找這兩個值中的任意一條 兩條都能找到
const datas = await User.find({ "bio.1": { $gt: 456 } }); // 使用下標指明指定數據的範圍 這裡找到第二條
如果查找的是數組對象中的某項
// 有這兩條數據
{
name: "4",
email: "[email protected]",
passWord: "357",
bio: [
{ head: 123, foot: 456 },
{ head: 456, foot: 789 },
],
},
{
name: "5",
email: "[email protected]",
passWord: "258",
bio: [
{ head: 123, foot: 789 },
{ head: 789, foot: 456 },
],
}
const datas = await User.find({ bio: { head: 123, foot: 789 } }); // 數組中含有這個對象就會找到,對象屬性要寫全,不能只寫部分,循序不能修改
const datas = await User.find({ "bio.foot": 789 }); // 數組中只要有一個對象符合就會找到,這裡兩個都會找到
const datas = await User.find({
bio: { $elemMatch: { foot: 456, head: { $gt: 100 } } }, // 使用$elemMatch 數組中擁有指定的對象就會找到,可以交換順序,可以使用限制,但是不能使用正則
});
第二個參數
限制返回數據含有的數據
const data = await User.find({ name: /\d/ }, { name: 1, email: 1, _id: 0 }); // _id默認帶著,這裡忽略了
第三個參數
可以使用keip limit sort
來對查詢結果進行操作
const data = await User.find({ name: /\d/ }, null, { skip: 1 }); // 這裡只會查找到 2 3
第二三個參數也能用鏈式調用的方法定義
查詢的結果支援鏈式調用,可以使用一些方法再對結果進行操作,相當於把第二個參數寫道外面了
-
select
:設置查詢結果的數據包含哪些鍵 接收列明字元串組成的數組,如果字元串前加上-
則是不顯示const datas = await User.find().select(["name", "-_id"]); // 查詢所有數據 返回對象只有name
-
limit
:限制查找結果的長度 -
skip
:設置查找結果的起式位置 -
sort
:對查找結果排序 接收列名字元串,按照從小到大排序,如果前面加上-
則會從大到小排const datas = await User.find().sort("-name"); // str 3 2 1 const datas = await User.find().sort("name"); // 1 2 3 str
-
count
:返回查找結果的數量 -
lean
:將結果返回為普通的js對象而不是查詢得到的Mongoose Documents
類型對象
常用的內置欄位:
欄位 | 說明 |
---|---|
$or | 或關係 |
$nor | 或關係取反 |
$gt | 大於 |
$gte | 大於等於 |
$lt | 小於 |
$lte | 小於等於 |
$ne | 不等於 |
$in | 在多個值範圍內 |
$nin | 不在多個值範圍內 |
$all | 匹配數組中多個值 |
$regex | 正則,用於模糊查詢 |
$size | 匹配數組大小 |
$maxDistance | 範圍查詢,距離(基於LBS) |
$mod | 取模運算 |
$near | 鄰域查詢,查詢附近的位置(基於LBS) |
$exists | 欄位是否存在 |
$elemMatch | 匹配內數組內的元素 |
$within | 範圍查詢(基於LBS) |
$box | 範圍查詢,矩形範圍(基於LBS) |
$center | 範圍醒詢,圓形範圍(基於LBS) |
$centerSphere | 範圍查詢,球形範圍(基於LBS) |
$slice | 查詢欄位集合中的元素(比如從第幾個之後,第N到第M個元素 |
通過Model.findOne
方法
該方法返回符合條件的第一條數據
通過Model.findById
方法
通過每個數據的_id
屬性查詢
刪
通過Model.remove
方法
不傳入參數會刪除該表的所有數據
該方法返回的是刪除數據的條數,不會返回被刪除數據
指定要刪除數據的某個鍵,鍵也可以使用正則表達式
const remove = await User.remove({ name: /\d/ });
也可以先查找,然後用數據的remove
方法
// 可以鏈式調用
const data = await User.find({ name: "1" }).remove();
// 也能迭代刪除
const data = await User.find({ name: "2" });
data.forEach((item) => {
item.remove();
});
通過Model.findOneAndRemove
方法
刪除符合條件的第一條數據,並將這條數據返回
通過Model.findByIdAndRemove
方法
通過_id
刪除
改
Model.update
已經不支援
通過Model.updateOne Model.updateMany
方法
該方法返回修改的資訊,不是返回修改後的數據
先指定查詢的條件,再在第二個參數放入修改的數據,第三個參數為一些設置
const datas = await User.updateOne({ name: "1" }, { $set: { name: "999" } }); // 將name為1的數據的name改為999
第三個參數如下,一般用不上
鍵名 | 默認值 | 說明 |
---|---|---|
safe | true | 安全模式 |
upsert | false | 是沒有這張表時是不是新建數據 |
setDefaultsOnInsert | 如果upsert選項為true,在新建時插入文檔定義的默認值 | |
strict | 以strict模式進行更新 | |
overwrite | false | 禁用update-only模式,允許覆蓋記錄 |
通過修改find findOne findById
找到的數據後調用save
方法
const data = await User.find({ name: "999" }); // data只會是一個數組 如果是findOne findById則不是
data.forEach((item) => {
item.name = "1";
item.save();
});
通過findOneAndUpdate findByIdAndUpdate
方法
是上面的語法糖,獲得修改後的數據