node-mongodb上手指南

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本地安裝

官方安裝說明: docs.mongodb.org/manual

安裝成功後啟動:

我本地是: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連接

  1. 創建連接對象,需要傳入連接資料庫的一些連接參數

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(); // 關閉連接 })

  1. 關閉連接

    關閉一個連接使用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,Model

const 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 自定義驗證規則

  1. 進行資料庫操作

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();

b. 修改

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: docs.mongodb.com/manual

mongodb查詢參數: mongodb-documentation.readthedocs.io

mongoose: mongoosejs.com/docs/api

blog:

cnblogs.com/zhongweiv/p

cnodejs.org/topic/504b4


推薦閱讀:

MongoDB 存儲引擎 mongorocks 原理解析
MongoDB複製集與Raft協議異同點分析
MongoDB與EDI系統集成
MongoDB-Elasticsearch 實時數據導入
MongoDB查詢過程explain參數詳解

TAG:MongoDB | mongoose | Nodejs |