node-mongodb上手指南
文章轉載自:node-mongodb上手指南
目錄:
1. MongoDB介紹2. MongoDB本地安裝3. MongoDB本地操作 3.1 庫操作 3.2 表操作4. node-mongodb安裝5. node-mongodb連接6. node-mongodb語法和執行 - 插入 - 查詢 - 修改 - 刪除 - 存儲過程7. node-mongoose介紹和使用 7.1 mongoose名詞介紹 7.2 node-mongoose安裝 7.3 node-mongoose安裝 7.4 node-mongoose語法和執行 7.4.1 Schema,Modal創建 - 索引和默認值 - 驗證器 7.4.2 資料庫操作 - 插入 - 刪除 - 修改 - 修改器和更新器 - 查詢 - 條件查詢 - 數量查詢 - 根據id查詢 - 分頁查詢 - aggregate8. 其他
1.mongodb介紹
開源,高性能的NoSQL資料庫;支持索引、集群、複製和故障轉移、各種語言的驅動程序;高伸縮性;
2. mongodb本地安裝
官方安裝說明: http://docs.mongodb.org/manual/tutorial/install-mongodb-on-windows/
安裝成功後啟動:
我本地是:mongod --dbpath "f:datadb"
MongoDB默認埠是27017;
3. mongodb本地操作
成功啟動MongoDB後,再打開一個命令行窗口輸入mongo,就可以進行資料庫的一些操作
a. 庫操作
新建資料庫:第一步:use 新建資料庫名;第二步:進行此庫相關的操作;如果不進行第二步,該資料庫不會被創建
- 查看資料庫:show dbs;- 新建表:db.createCollection(要新建的表名);- 查看當前資料庫下表: show collections;- 刪除當前資料庫指定表:db.表名.drop();- 刪除當前資料庫:db.dropDatabase();提示:
1. 默認為存在「admin」和「local」兩個資料庫;admin資料庫是存放管理員信息的資料庫,認證會用到;local是存放replication相關的數據;這兩處本篇都沒有涉及到;
2. find();是個查詢操作,後面會講到,上面用到主要是為了演示use不存在的庫後,進行相關操作會創建出這個庫;3. MongoDB沒有像MySQL或MSSQL等資料庫這麼嚴格的規定,不是非得要先建庫、建表、建各種欄位,以後的操作中慢慢的會體會到^_^!b. 表操作
1. 插入
方法一:db.表名.insert(數據); 1. 沒有去創建新表,其實通過插入操作也會自動創建2. _id,是mongodb自已生成的,每行數據都會存在,默認是ObjectId,可以在插入數據時插入這個鍵的值(支持mongodb支持的所有數據類型)方法二:db.表名.save(數據);
1. save也可達到insert一樣的插入效果2. _id可以自已插入3. 一個表中不一定要欄位都相同
那它們有什麼區別?
雖然insert和save方法都可以插入數據,當默認的「_id」值已存在時,調用insert方法插入會報錯;而save方法不會,會更新相同的_id所在行數據的信息2. 查詢
- 查詢表中所有數據:db.表名.find();- 按條件查詢(支持多條件):db.表名.find(條件); - 查詢第一條(支持條件):db.表名.findOne(條件);- 限制數量:db.表名.find().limit(數量);- 跳過指定數量:db.表名.find().skip(數量);查詢不止這些,還有些高級查詢,自行去了解一下^_^!
3. 修改
- 前面save在_id欄位已存在是就是修改操作,按指定條件修改語法如下:- db.表名.update({"條件欄位名":"欄位值"},{$set:{"要修改的欄位名":"修改後的欄位值"}});4. 刪除
- db.表名.remove(條件);5. 存儲過程
// 創建存儲過程:db.system.js.save({_id:"存儲過程ID", value:function(參數){ -- 邏輯主體; return 返回; }}); // 調用存儲過程db.eval("存儲過程ID()");
所有存儲過程都存放在db.system.js中
4. node-mongodb安裝
npm install mongodb
5. node-mongodb連接
- 創建連接對象,需要傳入連接資料庫的一些連接參數
const mongodbClient = require(mongodb).MongoClient; const url = mongodb://locolhost:27017; const dbName = test; // 資料庫名稱 mongodbClient.connect(url, function(err, client){ console.log(連接成功!); const db = client.db(dbName); const collection = db.collection(test); // 連接到表 // 執行mongo語句 ...... client.close(); // 關閉連接 })
- 關閉連接關閉一個連接使用close();
6. node-mongodb語法和執行
a. 插入
const insertData = function(collection, callback) { //插入數據 const data = [{"name":zhangsan,"age":21},{"name":lisi,"age":22}]; collection.insert(data, function(err, result) { if(err){ console.log(Error:+ err); return; } callback(result); });}mongodbClient.connect(url, function(err, client){ console.log(連接成功!); const db = client.db(dbName); const collection = db.collection(test); insertData(collection, function(result){ console.log(result); });})
b. 查詢
const selectData = function(collection, callback) { // 查詢所有 let whereStr = {"name":"張三"}; collection.find(whereStr).toArray(function(err, result) { if(err){ console.log(Error:+ err); return; } callback(result); }); // 條件查詢 查詢參數很多,自行查閱 collection.find({"age":{$gt:30}}).toArray(function(err, result) { if(err) { console.log(Error:+ err); return; } callback(result); });}......
c. 修改
const updateData = function(collection, callback) { const whereStr = {"name":zhangsan}; const updateStr = {$set: { "age" : 100 }}; collection.update(whereStr, updateStr, function(err, result) { if(err){ console.log(Error:+ err); return; } callback(result); });}
d: 刪除
var delData = function(db, callback) { //連接到表 var collection = db.collection(tb2); //刪除數據 var whereStr = {"name":wilson001}; collection.remove(whereStr, function(err, result) { if(err) { console.log(Error:+ err); return; } callback(result); });}
e: 存儲過程
const invokeProcData = function(db, callback) { db.eval(get_tb2_count(), function(err, result) { if(err) { console.log(Error:+ err); return; } callback(result); });}
7. mongoose介紹和使用
一般我們不直接用MongoDB的函數來操作MongoDB資料庫,針對它的進行再次封裝的東西很多,且更利於編程實現,比如:mongoose、mongoskin、mongolian等等,應用性不錯;
Mongoose就是一套操作MongoDB資料庫的介面,且應用較多。
1. 名詞解釋
- Schema: 一種以文件形式存儲的資料庫模型骨架,不具備資料庫的操作能力
- Schema.Type:是由Mongoose內定的一些數據類型,基本數據類型都在其中,他也內置了一些Mongoose特有的Schema.Type。當然,你也可以自定義Schema.Type,只有滿足Schema.Type的類型才能定義在Schema內。NodeJS中的基本數據類型都屬於Schema.Type,另外Mongoose還定義了自己的類型// 從官網截取過來的,舉例:var ExampleSchema = new Schema({ name:String, binary:Buffer, living:Boolean, updated:Date, age:Number, mixed:Schema.Types.Mixed, //該混合類型等同於nested _id:Schema.Types.ObjectId, //主鍵
_fk:Schema.Types.ObjectId, //外鍵
array:[], arrOfString:[String], arrOfNumber:[Number], arrOfDate:[Date], arrOfBuffer:[Buffer], arrOfBoolean:[Boolean], arrOfMixed:[Schema.Types.Mixed], arrOfObjectId:[Schema.Types.ObjectId] nested:{stuff:String,
}}); - Model: 由Schema發布生成的模型,具有抽象屬性和行為的資料庫操作對
- Entity: 由Model創建的實體,他的操作也會影響數據
Schema生成Model,Model創造Entity,Model和Entity都可對資料庫操作造成影響,但Model比Entity更具操作性
2. node-mongoose安裝
npm install mongoose
3. 連接mongoose
創建一個文件db.js:
const mongoose = require(mongoose), DB_URL = mongodb://localhost:27017/test;// 若有密碼,則url:mongodb://username:password@host:port/database?options...// 連接mongoose.connect(DB_URL);// 連接成功mongoose.connection.on(connected, function () { console.log(Mongoose connection open to + DB_URL); });// 連接異常mongoose.connection.on(error,function (err) { console.log(Mongoose connection error: + err); });// 連接斷開mongoose.connection.on(disconnected, function () { console.log(Mongoose connection disconnected); });module.exports = mongoose;
4. mongoose使用
舉例,創建了一個用戶登錄信息表,對此數據進行增刪改查
1. 創建文件user.js, 創建Schema,Modelconst mongoose = require(./db.js), Schema = mongoose.Schema; const UserSchema = new Schema({ username : { type: String, index: true }, //用戶賬號 userpwd: { type: String, required: true }, //密碼 userage: {type: Number, min: 18, max 80 }, //年齡 logindate : { type: Date, default: new Date()}, //最近登錄時間 city:{ type:String, enum:[北京,上海] }, // 城市 other:{ type:String, validate:[validator,err] //validator是一個驗證函數,err是驗證失敗的錯誤信息 } }); module.exports = mongoose.model(User,UserSchema);
上面有提到幾個定義
- 索引和默認值,即 index和default- 驗證器,即- required 非空驗證
- min/max 範圍驗證(邊值驗證) - enum/match 枚舉驗證/匹配驗證 - validate 自定義驗證規則- 進行資料庫操作
a. 插入
const User = require("./user.js");function insert() { const user = new User({ username : zhangsan, userpwd: abcd, userage: 37, logindate : new Date() }); user.save(function (err, res) { if (err) { console.log("Error:" + err); } else { console.log("Res:" + res); } });}insert();
const User = require("./user.js");function update(){ const wherestr = {username : zhangsan McGrady}; const updatestr = {userpwd: zzzz};User.update(wherestr, updatestr, function(err, res){ if (err) { console.log("Error:" + err); } else { console.log("Res:" + res); }})}update();
修改器和更新器:
為了更快進行更新的操作。在update中需要寫很多選擇器 $inc增減修改器,只對數字有效.下面的實例: 找到 age=22的文檔,修改文檔的age值自增1 Model.update({『age』:22}, {『$inc』:{『age』:1} } ); 執行後: age=23 $set指定一個鍵的值,這個鍵不存在就創建它.可以是任何MondoDB支持的類型 Model.update({『age』:22}, {『$set』:{『age』:』haha』} } ); 執行後: age=』haha』 $unset同上取反,刪除一個鍵 Model.update({『age』:22}, {『$unset』:{『age』:』haha』} } ); 執行後: age鍵不存在 $push給一個鍵push一個數組成員,鍵不存在會創建 Model.update({『age』:22}, {『$push』:{『array』:10} } ); 執行後: 增加一個 array 鍵,類型為數組, 有一個成員 10 $addToSet向數組中添加一個元素,如果存在就不添加 Model.update({『age』:22}, {『$addToSet』:{『array』:10} } ); 執行後: array中有10所以不會添加 $each遍曆數組, 和 $push 修改器配合可以插入多個值 Model.update({『age』:22}, {『$push』:{『array』:{『$each』: [1,2,3,4,5]}} } ); 執行後: array : [10,1,2,3,4,5] $pop向數組中尾部刪除一個元素 Model.update({『age』:22}, {『$pop』:{『array』:1} } ); 執行後: array : [10,1,2,3,4] tips: 將1改成-1可以刪除數組首部元素 $pull向數組中刪除指定元素 Model.update({『age』:22}, {『$pull』:{『array』:10} } ); 執行後: array : [1,2,3,4] 匹配到array中的10後將其刪除
c. 刪除
const User = require("./user.js");function del(){ const wherestr = {username : zhangsan}; User.remove(wherestr, function(err, res){ if (err) { console.log("Error:" + err); } else { console.log("Res:" + res); } })}del();
另外,刪除和更新的其他方法,常用方法有:
Model.findByIdAndUpdate(id, [update], [options], [callback]) // 找到指定id記錄並更新 Model.findOneAndUpdate([conditions], [update], [options], [callback]) // 找到一條記錄並更新 Model.findByIdAndRemove(id, [options], [callback]) // 找到指定id記錄並刪除 Model.findOneAndRemove(conditions, [options], [callback]) // 找到一條記錄並刪除const User = require("./user.js"); function findByIdAndUpdate(){ const id = 56f2558b2dd74855a345edb2; cibst updatestr = {userpwd: abcd}; User.findByIdAndUpdate(id, updatestr, function(err, res){ if (err) { console.log("Error:" + err); } else { console.log("Res:" + res); } }) } findByIdAndUpdate();
- d. 查詢查詢有直接查詢和鏈式查詢,鏈式查詢只有在執行exec方法時才執行查詢,而且必須有回調
- 條件查詢Model.find(conditions, [fields], [options], [callback])//fields和options是可選參數, field的值中,1為包括,0為不包括,options: 選項參數 //fields: 參數用於欄位映射,默認情況下,MongoDB會返回匹配文檔的所有欄位,使用映射(projection)設置希望返回的欄位,用於取文檔欄位的子集,相當於SQL中SELECT後面我們需要的欄位
- User.find({username : zhangsn}, {"username": 1 ,"_id": 0}, callback); // 輸出只會有username欄位,設置方法如上,1表示查詢輸出該欄位,0表示不輸出
- User.find({userage: {$gte: 21, $lte: 65}}, callback); // 這表示查詢年齡大於等21而且小於等於65歲參數還有: $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個元素* User.find({username:{$regex:/m/i}}, [callback]) // 模糊查詢,正則匹配有m的名字,且不區分大小寫
- 數量查詢Model.count(conditions, [callback]) // res結果會輸出數量,也可以傳入條件做條件查詢。
- 根據id查詢Model.findById(id, [fields], [options], [callback]) // 要據ID得到數據
- 分頁查詢
const User = require("./user.js");function getByPager(){ const pageSize = 5; //一頁多少條 const currentPage = 1; //當前第幾頁 const sort = {logindate:-1}; //排序(按登錄時間倒序) const condition = {}; //條件 const skipnum = (currentPage - 1) * pageSize; //跳過數 User.find(condition).skip(skipnum).limit(pageSize).sort(sort).exec(function (err, res) { if (err) { console.log("Error:" + err); } else { console.log("Res:" + res); } })}getByPager();
- e. aggregate在MongoDB中,聚合(aggregate)主要用於進行處理數據,比如統計求和,求平均數等,並返回計算後的數據結果,這給我們帶來了很多便捷之處,因為可以在讀取數據的同時進行數據處理例如:// $match用於獲取年齡大於20小於或等於40記錄,然後將符合條件的記錄送到下一階段$group管道操作符進行處理。User.aggregate([ { $match : { userage : { $gt : 20, $lte : 40 } } }, { $group: { _id: null, count: { $sum: 1 } } } ]);
下面列舉一些:
$project:修改輸入文檔的結構。可以用來重命名、增加或刪除域,也可以用於創建計算結果以及嵌套文檔。 $match:用於過濾數據,只輸出符合條件的文檔。$match使用MongoDB的標準查詢操作。 $limit:用來限制MongoDB聚合管道返回的文檔數。 $skip:在聚合管道中跳過指定數量的文檔,並返回餘下的文檔。 $unwind:將文檔中的某一個數組類型欄位拆分成多條,每條包含數組中的一個值。 $group:將集合中的文檔分組,可用於統計結果。 $sort:將輸入文檔排序後輸出。 $geoNear:輸出接近某一地理位置的有序文檔。更多參數可以參考下方參考鏈接。
8. 其他
注意:
- 表」應該描述為「collection(集合)」;「行」應該描述為「文檔(document)」,一個database中可以有多個collection,一個collection中又可以有多個document- 用CMD中使用mongo.exe操作時,插入中文遇一了問題,原因是MongoDB默認編輯是utf-8,而CMD是GBK,所以在CMD窗口中執行這個命令修改編輯即可:chcp 65001- 注意mongodb嚴格區分大小寫,比如查詢 db.tb2.find({"name":"wilson0"})和 db.tb2.find({"Name":"wilson0"}) 並不是用的同一欄位做的條件;參考:
mongodb: https://docs.mongodb.com/manual/reference/operator/aggregation/addFields/ mongodb查詢參數: https://mongodb-documentation.readthedocs.io/en/latest/reference/operator/gt.html mongoose: http://mongoosejs.com/docs/api.html#Aggregateblog:http://www.cnblogs.com/zhongweiv/p/node_mongodb.html https://cnodejs.org/topic/504b4924e2b84515770103dd推薦閱讀:
※MongoDB 存儲引擎 mongorocks 原理解析
※MongoDB複製集與Raft協議異同點分析
※MongoDB與EDI系統集成
※MongoDB-Elasticsearch 實時數據導入
※MongoDB查詢過程explain參數詳解