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 Model document概念

  • schema:表的結構,索引
  • Model:使用Schema實例獲得的具體的表,在這上面對表進行增刪改查
  • documentModel實例,相當於表中的每一條數據,Model中查到到的數據也是這種類型

創建表結構Schema

Schema相當於MySql的表結構

通過定義Schema來約束數據的類型,支持以下類型數據

類型 作用
String 定義字符串
Number 定義數字
Date 定義日期
Buffer 定義二進制
Boolean 定義布爾值
Mixed 定義混合類型
ObjectId 定義對象ID
Array 定義數組
Decimal128 定義小數
Map

約束能用對象的方法描述數據類型 是否必須 是否重復 默認值 等,如下定義了一個用戶表結構

注意:如果定義表結構時沒有定義_id,mongoose會自己添加一個該字段,該字段不會重復,類型為ObjectId,通過findById()查詢

在定義表結構時某些字段,如unique會自動創建索引,詳情見下章

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 數組中擁有指定的對象就會找到,可以交換順序,可以使用限制,但是不能直接使用正則,正則使用$regex
});

第二個參數

限制返回數據含有的數據

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

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


免責聲明!

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



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