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方法

是上面的語法糖,獲得修改後的數據

Tags: