下載
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: "123@qq.com", passWord: "123" },
{ name: "2", email: "456@qq.com", passWord: "456" },
{ name: "3", email: "789@qq.com", passWord: "789" }
);
res.status(200).json(users); // users是陣列
// 或者
User.create(
{ name: "str", email: "159@163.com", passWord: "159" },
{ name: "1", email: "123@qq.com", passWord: "123" },
{ name: "2", email: "456@qq.com", passWord: "456" },
{ name: "3", email: "789@qq.com", 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: "123@qq.com", passWord: "123" });
const users = await User.insertMany([
{ name: "2", email: "456@qq.com", passWord: "456" },
{ name: "3", email: "789@qq.com", 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: "357@163.com", 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: "357@163.com", passWord: "357", bio: [123, 456, "hahaha"] }
// { name: "5", email: "258@163.com", 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: "357@163.com",
passWord: "357",
bio: [
{ head: 123, foot: 456 },
{ head: 456, foot: 789 },
],
},
{
name: "5",
email: "258@163.com",
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 | 匹配陣列大小 |
$type | 匹配資料的型別 |
$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
方法
現在推薦使用
Model.deleteOne Model.deleteMany
來刪除 用法一樣不傳入引數會刪除該表的所有資料
該方法返回的是刪除資料的條數,不會返回被刪除資料
指定要刪除資料的某個鍵,鍵也可以使用正規表示式
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
方法
是上面的語法糖,獲得修改後的資料