摘要:查詢條件控制返回的字段控制選項回調(diào)函數(shù)。改查詢條件需要修改的數(shù)據(jù),不能修改主鍵控制選項回調(diào)函數(shù),返回的是受影響的行數(shù)。執(zhí)行查詢,回調(diào)函數(shù)。使用鏈?zhǔn)秸Z句時,可以在之后接執(zhí)行查詢,并指定回調(diào)函數(shù)。
初學(xué)Node.js接觸到MongoDB數(shù)據(jù)庫,閱讀資料中推薦的都是Mongoose模塊,可以更加方便的對數(shù)據(jù)庫進行操作,便開始接觸Mongoose。在學(xué)習(xí)時碰到許多基礎(chǔ)問題,查閱了許多資料理來理解,此篇文章就是以自己的理解,記錄下入門的基礎(chǔ)知識,以及歸納下常用的函數(shù)以及格式,方便今后查閱。
初學(xué)筆記難免有許多不足與錯誤歡迎指出。
如果需要在本地測試,需要先安裝MongoDB數(shù)據(jù)庫。
在官網(wǎng)下載最新安裝包。安裝成功后,在命令行下進入MongoDBin目錄
mongod --dbpath D:MongoDBdata
啟動數(shù)據(jù)庫。
http://localhost:27017/
在瀏覽器中訪問這地址,訪問正常則數(shù)據(jù)庫啟動成功。
更詳細(xì)的說明可以查看《MongoDB的下載、安裝與部署》
npm install mongoose
在已經(jīng)安裝過Node.js的電腦上,進入工作目錄輸入以上命令即可安裝Mongoose模塊。
可視化工具Robomongo是一款不錯的可視化工具,Windows、MacOS、Linux平臺都有,界面也簡潔。雖然有收費,普通操作免費版足夠用。
官網(wǎng)下載
在需要使用的js文件中引入模塊。
var mongoose = require("mongoose");連接數(shù)據(jù)庫
var db = mongoose.connect("mongodb://localhost/mongodb");
URL以mongodb:// + [用戶名:密碼@] +數(shù)據(jù)庫地址[:端口] + 數(shù)據(jù)庫名。(默認(rèn)端口27017)
需要對連接狀況進行判斷,可以用以下代碼:
db.connection.on("error", function (error) { console.log("數(shù)據(jù)庫連接失敗:" + error); }); db.connection.on("open", function () { console.log("數(shù)據(jù)庫連接成功"); }) db.connection.on("disconnected", function () { console.log("數(shù)據(jù)庫連接斷開"); })基本概念
最常接觸到的有三個概念Schema、Model、Entity。按自己理解,
Schema是定義數(shù)據(jù)庫的結(jié)構(gòu)。類似創(chuàng)建表時的數(shù)據(jù)定義,但比創(chuàng)建數(shù)據(jù)庫可以做更多的定義,只是沒辦法通過Schema對數(shù)據(jù)庫進行更改。
Model是將Schema定義的結(jié)構(gòu)賦予表名。但可用此名對數(shù)據(jù)庫進行增刪查改。
Entity是將Model與具體的數(shù)據(jù)綁定,可以對具體數(shù)據(jù)自身進行操作,例如保存數(shù)據(jù)。
Schema用來定義數(shù)據(jù)庫文檔結(jié)構(gòu),數(shù)據(jù)庫有什么字段、字段是什么類型、默認(rèn)值、主鍵之類的信息。除了定義結(jié)構(gòu)外,還能定義文檔的實例方法,靜態(tài)模型方法,復(fù)合索引,中間件等。詳情查看mongoose官方文檔。
在引入Mongoose模塊var mongoose = require("mongoose")的js文件中進行操作。
var blogSchema = new mongoose.Schema({ title: String, comments: [{ body: String, date: Date }], date: { type: Date, default: Date.now }, hidden: Boolean, meta: { votes: Number, favs: Number } })
這樣即定義了一個名為blogSchema的Schema。
如需再添加數(shù)據(jù),用add方法。
blogSchema.add( { author: String, body: String} );
資料中介紹,Shema不僅定義了文檔的結(jié)構(gòu)和屬性,還可以定義文檔的插件、實例方法、靜態(tài)方法、復(fù)合索引文檔生命周期鉤子,具體還需查看官方文檔。
Schema.TypeSchema.Type是Mongoose內(nèi)部定義的數(shù)據(jù)類型。基本類型有:String、Number、Date、Boolean、Array、Buffer、Mixed、ObjectId。
Mixed
混合數(shù)據(jù)類型,可以直接定義{}來使用,以下兩種形式等價。
new Schema({mixed: {Schema.Types.Mixed} }); new Schema({mixed: {} });
ObjectId
儲存在數(shù)據(jù)庫中的每個數(shù)據(jù)都會有默認(rèn)的主鍵_id,默認(rèn)存儲的是ObjectId。
ObjectId是一個12字節(jié)的BSON類型字符串。按照字節(jié)順序依次代表:
4字節(jié):UNIX時間戳
3字節(jié):表示運行MongoDB的機器
2字節(jié):表示生成此_id的進程
3字節(jié):由一個隨機數(shù)開始的計數(shù)器生成的值
var blogModel = mongoose.model("Blog", blogSchema);
將名為blogSchema的Schema與Blog名字綁定,即是存入數(shù)據(jù)庫的名字,但存入數(shù)據(jù)庫中的名字是Blogs,會自動添加一個s。
這里將Model命名為blogModel,需要對Blog表操作的話,都需要使用變量名blogModel。
可以綁定具體數(shù)據(jù)對Model實例化。
var blogEntity = new blogModel({ title: "Mongoose", author: "L", body: "Documents are instances of out model. Creating them and saving to the database is easy", comments: [{ body: "It"s very cool! Thanks a lot!", date: "2014.07.28" }], hidden: false, meta: { votes: 100, favs: 99 } })
這里將名為blogModel的Model實例化。之后我們可以用blogEntity名對數(shù)據(jù)進行保存并執(zhí)行回調(diào)。
blogEntity.save(function(err, docs){ if(err) console.log(err); console.log("保存成功:" + docs); })
在平常使用SQL語句操作數(shù)據(jù)庫時,取得數(shù)據(jù)后先組織成SQL語句,然后放入執(zhí)行語句中執(zhí)行。這里理解也是類似,取得數(shù)據(jù)先進行實例化,這一步類似于組織成SQL語句,然后再做具體操作例如上面的Save操作。但由于Node.js是異步操作,所以返回的數(shù)據(jù)利用回調(diào)函數(shù)來進行操作。
知道了以上概念后就可以對數(shù)據(jù)進行操作了,下面將列出一些常用的資料,并附上相應(yīng)的例子。
增查改刪(CRUD)所有的參數(shù)都是以JSON對象形式傳入。
增(C)Model.create(doc(s), [callback])
var doc = ({ title: "Mongoose", author: "L", body: "Documents are instances of out model. Creating them and saving to the database is easy", comments: [{ body: "It"s very cool! Thanks a lot!", date: "2014.07.28" }], hidden: false, meta: { votes: 100, favs: 99 } }; blogModel.create(doc, function(err, docs){ if(err) console.log(err); console.log("保存成功:" + docs); });
Model#save([options], [options.safe], [options.validateBeforeSave], [fn])
var blogEntity = new blogModel({ title: "Mongoose", author: "L", body: "Documents are instances of out model. Creating them and saving to the database is easy", comments: [{ body: "It"s very cool! Thanks a lot!", date: "2014.07.28" }], hidden: false, meta: { votes: 100, favs: 99 } }); blogEntity.save(function(err, docs){ if(err) console.log(err); console.log("保存成功:" + docs); });
Model.insertMany(doc(s), [options], [callback])
多條數(shù)據(jù)插入,將多條數(shù)據(jù)一次性插入,相對于循環(huán)使用create保存會更加快。
blogModel.insertMany([ {title: "mongoose1", author: "L"}, {title: "mongoose2", author: "L"} ], function(err, docs){ if(err) console.log(err); console.log("保存成功:" + docs); });查(R)
Model.find(conditions, [projection], [options], [callback])
conditions:查詢條件;projection:控制返回的字段;options:控制選項;callback:回調(diào)函數(shù)。
blogModel.find({title: "Mongoose", meta.votes: 100}, {title: 1, author: 1, body: 1}, function(err, docs){ if(err) console.log(err); console.log("查詢結(jié)果:" + docs); })
查詢“title”標(biāo)題為“Mongoose”,并且“meta”中“votes”字段值為“100”的記錄,返回僅返回“title”、“author”、“body”三個字段的數(shù)據(jù)。
Model.findOne([conditions], [projection], [options], [callback])
conditions:查詢條件;projection:控制返回的字段;options:控制選項;callback:回調(diào)函數(shù)。
只返回第一個查詢記錄。
Model.findById(id, [projection], [options], [callback])
id:指定_id的值;projection:控制返回的字段;options:控制選項;callback:回調(diào)函數(shù)。
改(U)Model.update(conditions, doc, [options], [callback])
conditions:查詢條件;doc:需要修改的數(shù)據(jù),不能修改主鍵(_id);options:控制選項;callback:回調(diào)函數(shù),返回的是受影響的行數(shù)。
options有以下選項:
safe (boolean): 默認(rèn)為true。安全模式。
upsert (boolean): 默認(rèn)為false。如果不存在則創(chuàng)建新記錄。
multi (boolean): 默認(rèn)為false。是否更新多個查詢記錄。
runValidators: 如果值為true,執(zhí)行Validation驗證。
setDefaultsOnInsert: 如果upsert選項為true,在新建時插入文檔定義的默認(rèn)值。
strict (boolean): 以strict模式進行更新。
overwrite (boolean): 默認(rèn)為false。禁用update-only模式,允許覆蓋記錄。
blogModel.update({title: "Mongoose"}, {author: "L"}, {multi: true}, function(err, docs){ if(err) console.log(err); console.log("更改成功:" + docs); })
以上代碼先查詢“title”為“Mongoose”的數(shù)據(jù),然后將它的“author”修改為“L”,“multi”為true允許更新多條查詢記錄。
Model.updateMany(conditions, doc, [options], [callback])
一次更新多條
Model.updateOne(conditions, doc, [options], [callback])
一次更新一條
Model.findByIdAndUpdate(id, [update], [options], [callback])
id:指定_id的值;update:需要修改的數(shù)據(jù);options控制選項;callback回調(diào)函數(shù)。
options有以下選項:
new: bool - 默認(rèn)為false。返回修改后的數(shù)據(jù)。
upsert: bool - 默認(rèn)為false。如果不存在則創(chuàng)建記錄。
runValidators: 如果值為true,執(zhí)行Validation驗證。
setDefaultsOnInsert: 如果upsert選項為true,在新建時插入文檔定義的默認(rèn)值。
sort: 如果有多個查詢條件,按順序進行查詢更新。
select: 設(shè)置數(shù)據(jù)的返回。
Model.findOneAndUpdate([conditions], [update], [options], [callback])
conditions:查詢條件;update:需要修改的數(shù)據(jù);options控制選項;callback回調(diào)函數(shù)。
options有以下選項:
new: bool - 默認(rèn)為false。返回修改后的數(shù)據(jù)。
upsert: bool - 默認(rèn)為false。如果不存在則創(chuàng)建記錄。
fields: {Object|String} - 選擇字段。類似.select(fields).findOneAndUpdate()。
maxTimeMS: 查詢用時上限。
sort: 如果有多個查詢條件,按順序進行查詢更新。
runValidators: 如果值為true,執(zhí)行Validation驗證。
setDefaultsOnInsert: 如果upsert選項為true,在新建時插入文檔定義的默認(rèn)值。
passRawResult: 如果為真,將原始結(jié)果作為回調(diào)函數(shù)第三個參數(shù)。
Model.remove(conditions, [callback])
blogModel.remove({author: "L"}, function(err, docs){ if(err) console.log(err); console.log("刪除成功:" + docs); })
刪除“author”值為“L”的記錄。
Model.findByIdAndRemove(id, [options], [callback])
id:指定_id的值;update:需要修改的數(shù)據(jù);options控制選項;callback回調(diào)函數(shù)。
options有以下選項:
sort: 如果有多個查詢條件,按順序進行查詢更新。
select: 設(shè)置數(shù)據(jù)的返回。
Model.findOneAndRemove(conditions, [options], [callback])
conditions:查詢條件;update:需要修改的數(shù)據(jù);options控制選項;callback回調(diào)函數(shù)。
options有以下選項:
sort: 如果有多個查詢條件,按順序進行查詢更新。
maxTimeMS: 查詢用時上限。
select: 設(shè)置數(shù)據(jù)的返回。
在之前的查詢說明中僅演示了確定值的查詢,如果遇到更加復(fù)雜的情況就需要使用其他一些方法。
詳細(xì)的文檔可以在這兒查找 mongodb查詢符。
Query#exec([operation], [callback])
執(zhí)行查詢,回調(diào)函數(shù)。
使用find()、$where之類查詢返回的是Mongoose自己封裝的Query對象,使用find()可以在函數(shù)最后接上回調(diào)來獲取查詢到的數(shù)據(jù)。
使用鏈?zhǔn)秸Z句時,可以在之后接.exec()執(zhí)行查詢,并指定回調(diào)函數(shù)。
blogModel.find({title: "Mongoose", meta.votes: 100}, {title: 1, author: 1, body: 1}).exec(function(err, docs){ if(err) console.log(err); console.log("查詢結(jié)果:" + docs); })
配合各種查詢符可以方便的實現(xiàn)復(fù)雜的查詢。
比如我需要查詢“title”中以“Mongoose”開頭,并且“meta”中“votes”的值小余100。并且按“meta”中“votes”的值升序排序。
blogModel.and([ { title: { $regex: "Mongoose.+","$options":"i"}}, { meta.votes: { $lt: 100}} ).sort({ meta.votes: 1} ).exec(function(err, docs){ if(err) console.log(err); console.log("查詢結(jié)果:" + docs); });比較查詢運算符
$equals 等于 / $gt 大于 / $gte 大于等于 / $lt 小余 / $lte 小余等于 / $ne 不等于 / $in 在數(shù)組中 / $nin 不在數(shù)組中
blogModel.find({meta.votes: {$lt: 100}});
查詢“meta”中的“votes”字段值小余100的數(shù)據(jù)。
blogModel.find({title: {$in: ["Mongoose", "Mongodb", "Nodejs"]}});
查詢“title”為“Mongoose”或“Mongodb”或“Nodejs”其中之一的數(shù)據(jù)。
邏輯查詢運算符$or 或 / $and 與 / $nor 非
blogModel.find({ $and: [ {meta.votes: {$gte: 50}}, {meta.votes: {$lt: 100}} ]});
查詢“meta”中的“votes”字段值大于等于50到小余100的數(shù)據(jù)。
blogModel.find({ $nor: [ {meta.votes: 50}, {meta.votes: 100} ]});
查詢“meta”中的“votes”字段值不等于50和不等于100的數(shù)據(jù)。
以上例子也可以寫成這樣形式,比較清晰,其他類同
blogModel.and([ {meta.votes: {$gte: 50}}, {meta.votes: {$lt: 100}} ]); blogModel.nor([ {meta.votes: 50}, {meta.votes: 100} ]);元素查詢運算符
$exists 查詢的字段值是否存在
blogModel.find({ title: {$exists: true}}); blogModel.where("title").exists(true);
查詢存在“title”字段的數(shù)據(jù)。
評估查詢運算符$mod 與數(shù)據(jù)進行取模運算篩選
blogModel.find({ meta.votes: {$mod: [4, 0]}}); blogModel.where("meta.votes").$mod(4, 0);
查找“meta”中的“votes”字段值與4取模后,值為0的數(shù)據(jù)。
$regex 使用正則表達式查詢數(shù)據(jù)
blogModel.find({ title: { $regex: "Mongoose.+","$options":"i"}});
搜索以“Mongoose”開頭的“title”字段,“options”中的“i”代表不區(qū)分大小寫。
$options參數(shù)與其余用法可以查看mongodb文檔中 $regex 一節(jié)。
$where 支持js表達式查詢
blogModel.find({ $where: "this.comments.length === 10 || this.name.length === 5" }); blogModel.$where(function() { return this.comments.length === 10 || this.name.length === 5; });數(shù)組查詢運算符
Query#all([path], val) 查詢數(shù)組的本身及超集
blogModel.find( tags: ["nodejs", "mongoose"]);
查詢“tags”的字段值同時包含有["nodejs", "mongoose"]的數(shù)據(jù)。只要值中包含此數(shù)組即返回數(shù)據(jù),若是只包含數(shù)組中的一個則不返回此數(shù)據(jù)。
Query#elemMatch(path, criteria) 查詢數(shù)組的交集
blogModel.find( $elemMatch: { tags: "mongoose", author: "L"});
查詢“tags”為“mongoose”或是“author”為“L”的數(shù)據(jù)。
Query#size([path], val) 查詢指定大小的數(shù)組
blogModel.find( tags: { $size: 2}); blogModel.where("tags").size(2);
查詢“tags”數(shù)組中包含兩個元素的數(shù)據(jù)。
其他常用的運算符Query#limit(val) 限制查詢返回的數(shù)量
blogModel.find( tags: "mongoose").limit(5);
查詢“tags”為“mongoose”的數(shù)據(jù),只返回前5個查詢結(jié)果。
Query#skip(val) 跳過前N個查詢結(jié)果
blogModel.find( tags: "mongoose").skip(10).limit(5);
查詢“tags”為“mongoose”的數(shù)據(jù),跳過前10個查詢結(jié)果,返回從第11個開始的五個查詢結(jié)果。
做分頁時常用到這兩個,但數(shù)據(jù)量過大時就會有性能問題。
Query#sort(arg) 對結(jié)果按某個指定字段進行排序
1、asc為升序,-1、desc為降序。可以對一個字段進行排序,也可以是多個。
blogModel.find( tags: "mongoose").skip(10).limit(5).sort("{ meta.votes: 1}");
查詢“tags”為“mongoose”的數(shù)據(jù),跳過前10個查詢結(jié)果,返回從第11個開始的五個查詢結(jié)果。之后按“votes”進行升序排序。
Query#count([criteria], [callback]) 計數(shù)
blogModel.count({ title: "mongoose"}, function(err, docs){});
統(tǒng)計“title”為“mongoose”數(shù)據(jù)的數(shù)量
Query#select(arg) 選擇指定字段
在查詢中可以選擇指定的查詢字段,或者排除指定的字段。+為包含,-為排除。
blogModel.select("title body");
只包含“title”、“body”字段。
blogModel.select("-title -body");
排除“title”、“body”字段。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/18952.html
摘要:在配置的時候使用絕對路徑替代相對路徑,有利于在排查故障時查找進程啟動的目錄。在添加授權(quán)用戶和開啟認(rèn)證后,這些警告會自動消失。投影文檔中字段為或真值表示包含,或假值表示排除,可以設(shè)置多個字段為或,但不能混合使用。 MongoDB 是免費開源的跨平臺 NoSQL 數(shù)據(jù)庫,命名源于英文單詞 humongous,意思是「巨大無比」,可見開發(fā)組對 MongoDB 的定位。與關(guān)系型數(shù)據(jù)庫不同,Mo...
摘要:在配置的時候使用絕對路徑替代相對路徑,有利于在排查故障時查找進程啟動的目錄。在添加授權(quán)用戶和開啟認(rèn)證后,這些警告會自動消失。投影文檔中字段為或真值表示包含,或假值表示排除,可以設(shè)置多個字段為或,但不能混合使用。 MongoDB 是免費開源的跨平臺 NoSQL 數(shù)據(jù)庫,命名源于英文單詞 humongous,意思是「巨大無比」,可見開發(fā)組對 MongoDB 的定位。與關(guān)系型數(shù)據(jù)庫不同,Mo...
摘要:通過構(gòu)造而成,除了具有定義的數(shù)據(jù)庫骨架以外,還可以具體的操作數(shù)據(jù)庫。通過創(chuàng)建的實體,它也可以操作數(shù)據(jù)庫。但比更具操作性。 原文鏈接:Mongoose 前言 學(xué)數(shù)據(jù)庫肯定需要知道怎么連接后臺Mongoose 是用來方便連接 MongoDB 與 node 的一個工具包是時候?qū)W習(xí)一波 nodejs連接MongoDB 連接數(shù)據(jù)庫前需要先打開數(shù)據(jù)庫 MongoDB yarn add mongoo...
閱讀 2668·2021-11-24 10:44
閱讀 1930·2021-11-22 13:53
閱讀 1953·2021-09-30 09:47
閱讀 3714·2021-09-22 16:00
閱讀 2446·2021-09-08 09:36
閱讀 2323·2019-08-30 15:53
閱讀 2799·2019-08-30 15:48
閱讀 1000·2019-08-30 15:44