1. 程式人生 > >nodejs操作mongodb增刪改查

nodejs操作mongodb增刪改查

1. Mac系統上安裝

使用Homebrew安裝

$ brew updata // 更新Homebrew的package資料庫
$ brew install mongodb

2. 啟動MongoDB

$mongod --config /usr/local/etc/mongod.conf
// sudo mongod

3. 使用MongoDB shell

$ mongo

MongoDB是什麼?

MongoDB是一個基於分散式檔案儲存的資料庫。由C++語言編寫。旨在為WEB應用提供可擴充套件的高效能資料儲存解決方案。 
特點是: 
高效能、易部署、易使用、儲存資料方便

MongoDB概念

SQL MongoDB 解釋
database database 資料庫
table collection 資料庫表/集合
row document 資料記錄行/文件
column field 資料欄位/域
index index 索引
table joins 表連線,MongoDB不支援
primary key primary key 主鍵,MongoDB自動將_id欄位設定為主鍵

1. 資料庫

  • 一個mongodb中可以建立多個數據庫
  • MongoDB的預設資料庫為“db”,該資料庫儲存在data目錄中。
  • MongoDB的單個例項可以容納多個獨立的資料庫,每一個都有自己的集合和許可權,不同的資料庫也放置在不同的檔案中
show dbs 列出所有資料庫
db //顯式當前使用的資料庫
use xxx 切換資料庫

資料庫的命名:通過識別符號,使用utf8字串

  • 非空
  • 不允許出現特殊字元$,/
  • 全部小寫,最多64個位元組
  • 有一些特殊保留資料庫,如local、admin、config,命名時避免使用

2. 文件

文件是一個鍵值(key-value)對(即BSON)。MongoDB的文件不需要設定相同的欄位,並且相同的欄位不需要相同的資料型別,這與關係型資料庫有很大的區別,也是MongoDB非常突出的特點。

3. 集合

集合就是 MongoDB文件組,類似於RDBMS(關係型資料庫管理系統)中的表格。 
集合存在於資料庫中,集合沒有固定的結構,這意味著對集合可以插入不同格式和型別的資料,但通常情況下我們插入的資料都會有一定的關聯性。

結合的命名

  • 不能是空字串
  • 不允許出現- 0
  • 不能以system.開頭,這是系統保留的字首
  • 不能包含保留字,$

4.MongoDB資料型別

型別 描述
null 用於表示空值或者不存在的欄位{“x”,null}
布林 ‘true’和’false’{“x”,true}
32位整數 Shell中這個型別不可用,MongoDB在控制檯使用JS引擎進行輸入,而JS僅支援64位浮點數,所以32位整數將會被自動轉義
64位整數 Shell中這個型別不可用, 64位整數與32位整數一樣,在MongoDB控制檯使用時,會轉義成64位浮點數
64位浮點數 Shell中的數字都是這種型別,下面是浮點數{“x”:3.14}、{“x”:3}
字串 UTF-8字串都可表示為字串型別的資料{“x”:”foobar”}
符號 Shell不支援這種型別,將自動轉義成字串
物件ID 物件id是文件的12位元組的唯一ID,時間戳
日期 日期型別儲存的是從標準紀元開始的毫秒數{“x”:new Date()}
正則表示式 文件中可以包含正則表示式,其正則表示式採用JS語法來表示{“x”:/foobar/i}
程式碼 文件中可以包含js程式碼{“x”:function(){…}}
二進位制資料 二進位制資料可以由任意位元組的串組成,不過Shell無法使用
最大值 BSON包括一個特殊型別,表示可能的最大值Shell無法使用
最小值 BSON包括一個特殊型別,表示可能的最小值Shell無法使用
未定義 文件中也可以使用未定義型別{“x”:undefined}
陣列 值的集合或者列表可以表示成陣列{“x”:[“a”,”b”,”c”]}
內嵌文件 文件可以包含別的文件{“x”:{“foo”:”bar”}}

MongoDB操作

1. 資料庫常用命名

  1. Help檢視提示命令 
    help 
    • db.help()
    • db.test.help()
    • db.test.find().help()
  2. 建立/切換資料庫 
    • use music
  3. 查詢資料庫 
    • show dbs
  4. 檢視當前使用的資料庫 
    • db/db.getName()
  5. 顯示當前DB狀態 
    • db.stats()
  6. 檢視當前DB版本 
    • db.version()
  7. 檢視當前DB的連結機器地址 
    • db.getMongo()
  8. 刪除資料庫 
    • db.dropDatabase()

2. shell操作資料庫

>  use music
switched to db music
>  show dbs // 當前列表裡沒有music資料庫,因為沒有資料
>  db.albums.insertOne({'title':'生命之花'})
{
    "acknowledged" : true,
    "insertedId" : ObjectId("591b158a71d7222a7a0d7f60")
}
> db.albums.find()
{ "_id" : ObjectId("591b158a71d7222a7a0d7f60"), "title" : "生命之花" }
> show dbs //插入資料後,有music資料庫
music    0.000GB
> db
music
> db.getName()
music
> db.stats()
{
    "db" : "music",
    "collections" : 1,
    "views" : 0,
    "objects" : 1,
    "avgObjSize" : 46,
    "dataSize" : 46,
    "storageSize" : 16384,
    "numExtents" : 0,
    "indexes" : 1,
    "indexSize" : 16384,
    "ok" : 1
}
> db.version()
3.4.3
> db.getMongo()
connection to 127.0.0.1:27017
> db.dropDatabase() //刪除資料庫
{ "dropped" : "music", "ok" : 1 }

Collection 聚集集合操作

1. 建立一個聚集集合

db.createCollection(“collName”, {size: 20, capped: true, max: 100}); 
db.collName.isCapped(); //判斷集合是否為定容量

> db.createCollection('albums',{size:20,capped:true,max:100})
{ "ok" : 1 }

capped:true 將集合固定大小,可以提高訪問資料庫的效率,插入資料時,會自動進行順序管理

> db.albums.isCapped() //判斷集合是否為定容量
true

size的優先順序大於max

2. 得到指定名稱的聚集集合

> db.getCollection('albums')
music.albums

3. 得到當前db的所有聚集集合

> db.getCollectionNames()
[ "albums" ]

4. 顯示當前db所有聚集的狀態

db.printCollectionStats()

新增、修改與刪除集合資料

1. 新增

> db.albums.insertOne({title:'生命之花'})
> db.albums.insertMany([{title:'再見理想'},{title:'飛船'}])
> db.albums.insert([{title:'光輝歲月'},{title:'hello'}])
> db.albums.save({title:'21'})

2. 修改

修改所有資料


db.albums.updateMany(
  {},
  {
    $set:{artist:'adele'}
  }
  )
> db.albums.find()
{ "_id" : ObjectId("591b1d7871d7222a7a0d7f61"), "title" : "生命之花", "artist" : "adele" }
{ "_id" : ObjectId("591b1e0071d7222a7a0d7f62"), "title" : "再見理想", "artist" : "adele" }
{ "_id" : ObjectId("591b1e0071d7222a7a0d7f63"), "title" : "飛船", "artist" : "adele" }
{ "_id" : ObjectId("591b1eac71d7222a7a0d7f64"), "title" : "光輝歲月", "artist" : "adele" }
{ "_id" : ObjectId("591b1eac71d7222a7a0d7f65"), "title" : "hello", "artist" : "adele" }
{ "_id" : ObjectId("591b1ee971d7222a7a0d7f66"), "title" : "21", "artist" : "adele" }

修改一條資料

>db db.albums.updateMany(
  {title:'光輝歲月'},
  {
    $set:{artist:'Beyond'}
  }
  )
{ "_id" : ObjectId("591b1eac71d7222a7a0d7f64"), "title" : "光輝歲月", "artist" : "Beyond" }

3. 刪除

刪除一條記錄

> db.albums.deleteOne({artist:'adele'})
{ "acknowledged" : true, "deletedCount" : 1 }
> db.albums.remove({artist:'adele'},true)
WriteResult({ "nRemoved" : 1 })

刪除多條記錄

> db.albums.deleteMany({artist:'adele'})
{ "acknowledged" : true, "deletedCount" : 3 }
> db.albums.remove({})
WriteResult({ "nRemoved" : 1 })

4. 查詢修改刪除

db.users.findAndModify({
    query: {age: {$gte: 25}}, 
    sort: {age: -1}, 
    update: {$set: {name: 'a2'}, $inc: {age: 2}},
    remove: true
});
db.runCommand({ findandmodify : "users", 
    query: {age: {$gte: 25}}, 
    sort: {age: -1}, 
    update: {$set: {name: 'a2'}, $inc: {age: 2}},
    remove: true
});
引數 詳解 詳解
query 查詢過濾條件 {}
sort 如果多個文件符合查詢過濾條件,將以該引數指定的排列方式選擇出排在首位的物件,該物件將被操作 {}
remove 若為true,被選中物件將在返回前被刪除 N/A
update 一個 修改器物件 N/A
new 若為true,將返回修改後的物件而不是原始物件。在刪除操作中,該引數被忽略。 FALSE
upsert 建立新物件若查詢結果為空 FALSE

聚集集合查詢

1. 查詢所有記錄

db.userInfo.find(); 
相當於:select* from userInfo;

2.查詢去重後資料

db.userInfo.distinct(“name”); 
相當於:select distict name from userInfo;

3. 查詢age = 22的記錄

db.userInfo.find({“age”: 22}); 
相當於: select * from userInfo where age = 22;

4. 查詢age > 22的記錄

db.userInfo.find({age: {$gt: 22}}); 
相當於:select * from userInfo where age >22;

5. 查詢age < 22的記錄

db.userInfo.find({age: {$lt: 22}}); 
相當於:select * from userInfo where age <22;

6. 查詢age >= 25的記錄

db.userInfo.find({age: {$gte: 25}}); 
相當於:select * from userInfo where age >= 25;

7. 查詢age <= 25的記錄

db.userInfo.find({age: {$lte: 25}});

8. 查詢age >= 23 並且 age <= 26

db.userInfo.find({age: {gte:23,gte:23,lte: 26}}); 
查詢name中包含 mongo的資料

9. db.userInfo.find({name: /mongo/});

//相當於%% 
select * from userInfo where name like ‘%mongo%’;

10. 查詢name中以mongo開頭的

db.userInfo.find({name: /^mongo/}); 
select * from userInfo where name like ‘mongo%’;

11. 查詢指定列name、age資料

db.userInfo.find({}, {name: 1, age: 1}); // 只訪問name和age兩列的內容,1位標識 
相當於:select name, age from userInfo;

12. 查詢指定列name、age資料, age > 25

db.userInfo.find({age: {$gt: 25}}, {name: 1, age: 1}); 
相當於:select name, age from userInfo where age >25;

13. 按照年齡排序

升序:db.userInfo.find().sort({age: 1}); // 1 為標識,升序 
降序:db.userInfo.find().sort({age: -1}); // -1 為標識,降序

14.查詢name = zhangsan, age = 22的資料

db.userInfo.find({name: ‘zhangsan’, age: 22}); 
相當於:select * from userInfo where name = ‘zhangsan’ and age = ’22’;

15.查詢前5條資料

db.userInfo.find().limit(5); 
相當於:select top 5 * from userInfo;

16. 查詢10條以後的資料

db.userInfo.find().skip(10); 
相當於:select * from userInfo where id not in ( 
select top 10 * from userInfo 
);

17. 查詢在5-10之間的資料

db.userInfo.find().limit(10).skip(5);

18. or與 查詢

db.userInfo.find({$or: [{age: 22}, {age: 25}]}); 
相當於:select * from userInfo where age = 22 or age = 25;

19. 查詢第一條資料

db.userInfo.findOne(); 
相當於:selecttop 1 * from userInfo; 
db.userInfo.find().limit(1);

20. 查詢某個結果集的記錄條數

db.userInfo.find({age: {$gte: 25}}).count(); 
相當於:select count(*) from userInfo where age >= 20;

21. 按照某列進行排序

db.userInfo.find({sex: {$exists: true}}).count(); 
相當於:select count(sex) from userInfo;

聚集集合查詢shell 操作

#

db.movie.find({year:'1994'},{title:1, year:1})
{ "_id" : ObjectId("591b296971d7222a7a0d7f67"), "title" : "肖申克的救贖", "year" : "1994" }
{ "_id" : ObjectId("591b296971d7222a7a0d7f68"), "title" : "這個殺手不太冷", "year" : "1994" }
{ "_id" : ObjectId("591b296971d7222a7a0d7f6a"), "title" : "阿甘正傳", "year" : "1994" }

若不顯示_id欄位內容

> db.movie.find({year:'1994'},{title:1, year:1, _id:0})
{ "title" : "肖申克的救贖", "year" : "1994" }
{ "title" : "這個殺手不太冷", "year" : "1994" }
{ "title" : "阿甘正傳", "year" : "1994" }

顯式title,year和rating.averag

db.movie.find({},{title:1, year:1, 'rating.average':1, _id:0})
{ "rating" : { "average" : 9.6 }, "title" : "肖申克的救贖", "year" : "1994" }
{ "rating" : { "average" : 9.4 }, "title" : "這個殺手不太冷", "year" : "1994" }
{ "rating" : { "average" : 9.5 }, "title" : "霸王別姬", "year" : "1993" }
{ "rating" : { "average" : 9.4 }, "title" : "阿甘正傳", "year" : "1994" }
{ "rating" : { "average" : 9.5 }, "title" : "美麗人生", "year" : "1997" }
{ "rating" : { "average" : 9.2 }, "title" : "千與千尋", "year" : "2001" }
{ "rating" : { "average" : 9.4 }, "title" : "辛德勒的名單", "year" : "1993" }
{ "rating" : { "average" : 9.2 }, "title" : "泰坦尼克號", "year" : "1997" }
{ "rating" : { "average" : 9.2 }, "title" : "盜夢空間", "year" : "2010" }
{ "rating" : { "average" : 9.3 }, "title" : "機器人總動員", "year" : "2008" }
{ "rating" : { "average" : 9.2 }, "title" : "海上鋼琴師", "year" : "1998" }
{ "rating" : { "average" : 9.1 }, "title" : "三傻大鬧寶萊塢", "year" : "2009" }
{ "rating" : { "average" : 9.2 }, "title" : "忠犬八公的故事", "year" : "2009" }
{ "rating" : { "average" : 9.2 }, "title" : "放牛班的春天", "year" : "2004" }
{ "rating" : { "average" : 9.2 }, "title" : "大話西遊之大聖娶親", "year" : "1995" }
{ "rating" : { "average" : 9.2 }, "title" : "教父", "year" : "1972" }
{ "rating" : { "average" : 9.1 }, "title" : "龍貓", "year" : "1988" }
{ "rating" : { "average" : 9 }, "title" : "楚門的世界", "year" : "1998" }
{ "rating" : { "average" : 9.2 }, "title" : "亂世佳人", "year" : "1939" }
{ "rating" : { "average" : 9.1 }, "title" : "天堂電影院", "year" : "1988" }

符合條件的條數

db.movie.find({},{title:1, year:1, 'rating.average':1, _id:0}).size()
20

limit 顯式指定數目

> db.movie.find({},{title:1, year:1, 'rating.average':1, _id:0}).limit(5)
{ "rating" : { "average" : 9.6 }, "title" : "肖申克的救贖", "year" : "1994" }
{ "rating" : { "average" : 9.4 }, "title" : "這個殺手不太冷", "year" : "1994" }
{ "rating" : { "average" : 9.5 }, "title" : "霸王別姬", "year" : "1993" }
{ "rating" : { "average" : 9.4 }, "title" : "阿甘正傳", "year" : "1994" }
{ "rating" : { "average" : 9.5 }, "title" : "美麗人生", "year" : "1997" }

skip 跳過制定數的資料

> db.movie.find({},{title:1, year:1, 'rating.average':1, _id:0}).skip(15)
{ "rating" : { "average" : 9.2 }, "title" : "教父", "year" : "1972" }
{ "rating" : { "average" : 9.1 }, "title" : "龍貓", "year" : "1988" }
{ "rating" : { "average" : 9 }, "title" : "楚門的世界", "year" : "1998" }
{ "rating" : { "average" : 9.2 }, "title" : "亂世佳人", "year" : "1939" }
{ "rating" : { "average" : 9.1 }, "title" : "天堂電影院", "year" : "1988" }

limit和skip 3-5條資料

> db.movie.find({},{title:1, year:1, 'rating.average':1, _id:0}).skip(2).limit(3)
{ "rating" : { "average" : 9.5 }, "title" : "霸王別姬", "year" : "1993" }
{ "rating" : { "average" : 9.4 }, "title" : "阿甘正傳", "year" : "1994" }
{ "rating" : { "average" : 9.5 }, "title" : "美麗人生", "year" : "1997" }

sort 排序 1 為升序,-1為降序

> db.movie.find({},{title:1, year:1, 'rating.average':1, _id:0}).sort({'rating.average':1})

條件查詢

> db.movie.find({'rating.average':{$gt:9.4}},{title:1, 'rating.average':1, _id:0})
{ "rating" : { "average" : 9.6 }, "title" : "肖申克的救贖" }
{ "rating" : { "average" : 9.5 }, "title" : "霸王別姬" }
{ "rating" : { "average" : 9.5 }, "title" : "美麗人生" }

按指定內容查詢

> db.movie.find({genres:{$in:['犯罪']}},{title:1, genres:1, _id:0})
{ "genres" : [ "犯罪", "劇情" ], "title" : "肖申克的救贖" }
{ "genres" : [ "劇情", "動作", "犯罪" ], "title" : "這個殺手不太冷" }
{ "genres" : [ "劇情", "犯罪" ], "title" : "教父" }

node中使用MongoDB

var mongodb = require('mongodb')

// 建立資料庫的連線

var server = new mongodb.Server(
  'localhost',
  27017,
  {auto_reconnect:true}
)

// 建立資料的連線
var db = new mongodb.Db(
  'movies',
  server,
  {safe: true}
)

// 測試資料庫連線
db.open(function(err, db){
  if (err){
    console.log('log-'+ err)
  } else {
    console.log('log-connect mongodb success')
    db.collection('movie', {safe: true}, function(err, conn){
      if (err){
        console.log(err)
      } else {
        conn.find({}, {title:1, year:1, _id:0}).limit(3).skip(3).toArray(function(err, res){
          if(!err){
            res.forEach(function(value){
              console.log(value.title)
            })
          }
        })
      }
    })
  }
})
//列印結果
//阿甘正傳
//美麗人生
//千與千尋