快速掌握mongoDB(一)——mongoDB安裝部署和經常使用shell命令

1.mongoDB簡介

  mongoDB 是由C++語言編寫的,是一種分佈式的面向文檔存儲的開源nosql數據庫。nosql是Not Only SQL的縮寫,是對不一樣於傳統的關係型數據庫的數據庫管理系統的統稱。javascript

  mongoDB是無模式的文檔數據庫,在關係型數據庫中,數據表的每一行都擁有同樣的字段,字段的名字和數據類型在建立table的時候就基本肯定了,如student表的每一行都有學生編號、學生姓名、年齡等字段;而在mongoDB中,存儲數據的格式相似於Json(格式爲Bson),每個document的字段的名字和數據類型能夠徹底不一樣,如在一個collection下,第一個document能夠存儲學生信息(學生編號、姓名、年齡、性別等),第二個document能夠存儲班級信息(班級編號,班級名等)。正是由於無模式的特色,讓咱們能夠無需多餘操做就能完成數據的橫向擴展。下表是mongoDB和傳統數據庫術語的對應關係。java

SQL術語 MongoDB 解釋/說明
database database 數據庫
table collection 數據庫表/集合
row document 數據記錄行/文檔
column field 數據字段/域
index index 索引
join  $lookup 錶鏈接
primary key primary key 主鍵,MongoDB自動將_id字段設置爲主鍵

 

2. mongoDB安裝 

1.安裝mongoDB

  mongoDB的安裝步驟十分簡單,下載地址:https://www.mongodb.com/download-center#community。若是咱們想在Windows上安裝mongoDB直接下載msi文件,雙擊安裝便可。若是要將mongoDB安裝在Linux系統上,步驟以下:linux

####第1步 下載解壓mongdb
#下載解壓二進制包,解壓即安裝
  cd /usr/local/src/
  curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.9.tgz
  tar -zxvf mongodb-linux-x86_64-4.0.9.tgz
  mv mongodb-linux-x86_64-4.0.9 /usr/local/mongodb

####第2步 添加配置文件
  vim /usr/local/mongodb/bin/mongodb.conf
配置文件內容以下:
systemLog: destination: file logAppend: true path: /usr/local/mongodb/logs/mongodb.log
storage:
  dbPath: /usr/local/mongodb/data
  journal:
    enabled: true
processManagement:
  fork: true
net:
  port: 27017
  bindIp: 0.0.0.0

 #配置文件中指定的dbpath和log要本身添加,否則會報錯,執行命令 
  mkdir -p /usr/local/mongodb/data; mkdir -p /usr/local/mongodb/logs/;cd /usr/local/mongodb/logs/; touch mongodb.log

 ####第3步 加載配置文件運行
  /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/bin/mongodb.conf 

####第4步 添加環境變量,用於能夠在任意目錄下執行mongo命令 
  vim ~/.bash_profile #修改當前用戶下的環境變量 PATH=$PATH:$HOME/bin:/usr/local/mongodb/bin  
  source ~/.bash_profile

  安裝完成後,在任意目錄下使用命令 mongo 192.168.70.133:27017 (mongo命令會默認啓動127.0.0.1:27017)啓動mongodb,mongoDB使用的是javascript shell,咱們簡單測試一下,若是出現下邊的界面表示安裝成功了sql

 

   這裏簡單使用一下mongoDB的shell來添加、刪除數據庫和collection:mongodb

2.安裝Robomongo並鏈接數據庫

  mongoDB的GUI有MongoDB Compass、studio 3T等,這裏使用的是Robomongo,下載地址:https://robomongo.org/,下載完成後一直Next安裝便可,鏈接mongoDB效果以下,Robomongo是傻瓜式的用法,能夠經過客戶端添加collection,document,執行shell等,具體使用方法就再也不詳細介紹了。shell

·  數據庫

  咱們也能夠經過shell腳本鏈接數據庫,在Robomongo執行shell命令以下:json

//鏈接遠程數據庫
  var mongo=new Mongo("192.168.70.133:27017")
//找到數據庫
  var db=mongo.getDB("myDB");
//找到collecttion
  var collection=db.getCollection("userinfo");
//查詢colletion中全部數據
  var list=collection.find().toArray();
//json形式打印結果
  printjson(list);

3 mongoDB的shell

  咱們已經知道mongoDB是面向文檔的nosql數據庫,由於其無模式的特色,形成它的操做要比關係型數據庫複雜一些,這裏簡單介紹一下mongoDB的CRUD操做。注意:從3.2版本開始,mongoDB添加了一些xxxOne()和xxxMany()方法,咱們儘可能使用這些新的方法。vim

1 添加(insert)

   添加數據的指令是insert,使用方法以下:數組

 

   

  insert方法的參數也能夠是數組,用於批量添加數據,以下:

db.userinfos.insert([
   {_id:1, name: "張三", age: 23},
   {_id:2, name: "李四", age: 24}
]);

  從3.2版本,mongoDB添加了insertOne和insertMany方法,分別用於單條插入和批量插入,用法很簡單,以下:

//insertOne用於單條添加
  db.userinfos.insertOne(
     {_id:1, name: "張三", age: 23}
    );

//insertMany用於批量添加
   db.userinfos.insertMany([
     {_id:1, name: "張三", age: 23},
     {_id:2, name: "李四", age: 24}
  ]);

2 查詢(find)

  mongoDB查詢使用find函數,語法以下:

  

  mongoDB使用find查詢時,默認會返回主鍵_id,若是不想返回主鍵的話設置_id=0便可。mongoDB的查詢語法是比較簡單的,可是由於其無模式的特色,且field的值能夠是對象和數組,形成mongoDB的運算符要比傳統的關係型數據庫多不少,如運算符$exists可用於查詢field是否存在、$type用於判斷filed的類型等等,這裏彙總了一些經常使用的查詢相關的運算符,有興趣的小夥伴能夠測試一下:

測試數據:

db.userinfos.insertMany([ {_id:1, name: "張三", age: 23,level:10, ename: { firstname: "san", lastname: "zhang"}, roles: ["vip","gen" ]}, {_id:2, name: "李四", age: 24,level:20, ename: { firstname: "si", lastname: "li"}, roles:[ "vip" ]}, {_id:3, name: "王五", age: 25,level:30, ename: { firstname: "wu", lastname: "wang"}, roles: ["gen","vip" ]}, {_id:4, name: "趙六", age: 26,level:40, ename: { firstname: "liu", lastname: "zhao"}, roles: ["gen"] }, {_id:5, name: "田七", age: 27, ename: { firstname: "qi", lastname: "tian"}, address:'北京' }, {_id:6, name: "周八", age: 28,roles:["gen"], address:'上海' } ]);
 類別  運算符  說明  實例  執行結果

比較運算符   

$gt($gte) 大於(大於等於)

db.userinfos.find(
  { age:{$gt:25}},
  { name:1 }

)

查找age>25的文檔的name

結果:

  [{ "_id" : 4, "name" : "趙六" },

   { "_id" : 5, "name" : "田七" }]

 $lt($lte)  小於(小於等於)  db.userinfos.find(

  { age:{$lt:25}},
  { name:1 }

)

查找age<25的文檔的name

結果: 

  [ { "_id" : 1, "name" : "張三" },

  { "_id" : 2, "name" : "李四" } ]

 $eq  等於  db.userinfos.find(

  { age:{$eq:25}},
  { name:1 }

)

查詢age=25的文檔的name

 結果:

  [ { "_id" : 3, "name" : "王五" } ]

 $ne  不等於

db.userinfos.find(
  { age:{$ne:25}},
  { name:1 }
)

 查詢age!=25的文檔的name

結果:

  [{"_id" : 1,"name" : "張三"},
  {"_id" : 2,"name" : "李四"},
  {"_id" : 4,"name" : "趙六"},
  {"_id" : 5,"name" : "田七"}]

 $in  包含  db.userinfos.find(

  { age:{$in:[24,25]}},
  { name:1 }
)

查詢age在[24,25]中的文檔的name

結果:

   [ { "_id" : 2, "name" : "李四" },

  { "_id" : 3, "name" : "王五" } ]

 $nin  不包含 db.userinfos.find(

  { age:{$nin:[24,25]}},
  { name:1 }
)

查詢age不在[24,25]中的文檔的name

結果:

  [{"_id" : 1,"name" : "張三"},
  {"_id" : 4,"name" : "趙六"},
  {"_id" : 5,"name" : "田七"}]

邏輯運算符 $and  與

db.userinfos.find(

  {$and: [

    {name:{$eq:'張三'}},

    {age:{$eq:23}}

  ]},

  {name:1}

)

 

查詢name='張三'且age=23的文檔 

結果:

  [ { "_id" : 1, "name" : "張三" } ]

$not   

 db.userinfos.find(

  {age:{$not:{$in:[23,24,25]}}},
  {name:1}
)

查詢age不在[23,24,24]中的文檔

結果:

  [ { "_id" : 4, "name" : "趙六" },

  { "_id" : 5, "name" : "田七" } ]

$or   或

 

 db.userinfos.find(

  {$or: [

    {name:{$eq:'張三'}},

    {age:{$eq:24}}

  ]},

  {name:1}

)

 

查詢name='張三'或者age=24的文檔 

結果:

  [ { "_id" : 1, "name" : "張三" },

  { "_id" : 2, "name" : "李四" } ]

$nor   

或的取反

 db.userinfos.find(

  {$nor: [

    {name:{$eq:'張三'}},

    {age:{$eq:24}}

  ]},

  {name:1}

)

 上邊栗子的取反操做

結果:

  [ {"_id" : 3,"name" : "王五"},
   {"_id" : 4,"name" : "趙六"},
   {"_id" : 5,"name" : "田七"} ]

 評估運算符 $mod 取餘

db.userinfos.find(

  {age:{$mod:[10,3]}},
  {name:1}
)

查詢name%10=3的文檔

結果:

[ { "_id" : 1, "name" : "張三" } ]

$regex  正則  

db.userinfos.find(

  {name:{$regex:/^張/i}},
  {name:1}
)

查詢name以張開頭的文檔

結果:

[ { "_id" : 1, "name" : "張三" } ]

db.userinfos.find(

  {name:{$in:[/^張/,/四$/]}},
  {name:1}
)

查詢name以張開頭或者以四結尾的文檔

結果:

[ { "_id" : 1, "name" : "張三" },

{ "_id" : 2, "name" : "李四" } ]

$where where過濾

db.userinfos.find(
  {$where :function(){return this.name=='張三';}},
  {name:1}

)

查詢名字爲張三的記錄

結果:

  [ { "_id" : 1, "name" : "張三" } ]

注意:where能夠實現全部的過濾,可是效率不高。

這是由於where採用逐行判斷而不使用索引

 $expr  表達式過濾

db.userinfos.find(
  { $expr:{$lt:["$age","$level"]}},
  { name:1 }

)

 查詢age<level的記錄

結果:

[ { "_id" : 3, "name" : "王五" },

{ "_id" : 4, "name" : "趙六" } ]

 

元素運算符   $exists field是否存在

db.userinfos.find(
  { address:{$exists:true}},
  { name:1 }

)

查詢存在address字段的文檔

結果:

[ { "_id" : 5, "name" : "田七" },

{ "_id" : 6, "name" : "周八" } ]

$type field類型

db.userinfos.find(

  {name:{$type:'string'}},

  {name:1}

)

 查詢name爲string的文檔

結果:

  全部文檔都匹配

數組運算符     $all  包含全部元素才匹配成功  db.userinfos.find(

  {roles:{$all:['vip','gen']}},

  {name:1}

)

查詢roles中包含vip和gen的文檔

結果:

 [ { "_id" : 1, "name" : "張三" },

{ "_id" : 3, "name" : "王五" } ]

 $eleMatch  只要有一個元素符合就匹配成功  db.userinfos.find(

  {roles:{$elemMatch:{ $eq: 'vip', $ne: 'gen' }}},

  {name:1}

)

 查詢roles中有元素等於vip,或有元素不等於gen的文檔

結果:

  [{"_id" : 1,"name" : "張三"},
  {"_id" : 2,"name" : "李四"},
  {"_id" : 3,"name" : "王五"}]

$size  元素個數相同的匹配成功  db.userinfos.find(

  {roles:{$size:2}},

  {name:1}

)

 查詢roles中有兩個元素的文檔

結果:

[ { "_id" : 1, "name" : "張三" },

{ "_id" : 3, "name" : "王五" } ]

3 修改(update)

  mongoDB修改documen使用的命令是update,語法以下:

  mongoDB的update默認只修改一條document,若是想修改全部符合條件的documet的話,能夠設置multi:true。upsert表示當沒有符合過濾條件的文檔時,就添加一條文檔,並將修改的內容做爲新增document的值。mongoDB的update功能比較豐富,如能夠修改field的名字,刪除field,以及對數組進行增刪改。從3.2版本開始,mongoDB添加了updateOne()和updateMany()方法,用於修改單條或者多條數據,推薦使用新的方法,語法以下:

 //將age<25的記錄的level修改成50,只修改一條。updateOne至關於update設置multi:false
db.userinfos.updateOne(
   {age:{$lt:25}},
   {$set:{level:50}}
   )
 //將age<25的記錄的level修改成50,全部符合條件的記錄都修改。updateMany至關於update設置multi:true
db.userinfos.updateMany(
   {age:{$lt:25}},
   {$set:{level:50}}
   )

  這裏彙總了mongoDB中關於update的相關運算符,有興趣的小夥伴能夠測試一下:

 測試數據:

db.userinfos.insertMany([ {_id:1, name: "張三", age: 23,level:10, ename: { firstname: "san", lastname: "zhang"}, roles: ["vip","gen" ]}, {_id:2, name: "李四", age: 24,level:20, ename: { firstname: "si", lastname: "li"}, roles:[ "vip" ]}, {_id:3, name: "王五", age: 25,level:30, ename: { firstname: "wu", lastname: "wang"}, roles: ["gen","vip" ]}, {_id:4, name: "趙六", age: 26,level:40, ename: { firstname: "liu", lastname: "zhao"}, roles: ["gen"] }, {_id:5, name: "田七", age: 27, ename: { firstname: "qi", lastname: "tian"}, address:'北京' }, {_id:6, name: "周八", age: 28,roles:["gen"], address:'上海' } ]);
 值操做運算符 $currentDate

修改field值爲當前時間,

若是field不存在則添加field

db.userinfos.update(
  {name:'張三'},
  {$currentDate:{

    createtime:{$type:'timestamp'}}

  }
)

將張三的createtime字段值修改成當前時間

  格式爲時間戳("createtime" : Timestamp(1560663270, 1))

補充:若是不設置$type,默認的格式爲date

  格式爲date("createtime" : ISODate("2019-06-16T05:38:21.119Z"))

  

$set

修改值

db.userinfos.update(
  {name:'張三'},
  {$set:

    {level:20}

  }
)

 將張三的level修改成20。若是要修改的field不存在,不會添加新的field。
$setOnInsert 

只有在新增document時進行賦值,

必定要設置upsert:true

 

db.userinfos.update(
  {name:'張三'},
  {$setOnInsert:

    {level:30}

  },
  {upsert:true}
)

 由於已經有name=張三的document,因此不作任何操做

db.userinfos.update(
  {name:'吳九'},
  {$setOnInsert:{level:30}},
  {upsert:true}
)

 添加一個name=吳九的document,並設置level爲30
$inc 自增

db.userinfos.update(
  {name:'張三'},
  {$inc:

    {age:10}

  }
)

張三的age自增10,age修改成23+10=33
$mul 自乘

db.userinfos.update(
  {name:'張三'},
  {$mul:

    {age:2}

  }
)

張三的age自乘2,age修改成23*2=46
$min 取小

db.userinfos.update(
  {name:'張三'},
  {$min:

    {age:13}

  }
)

張三的age取小值,由於23>13,因此修改age爲13。若是修改的值比23大,那麼不作操做。
$max 取大

db.userinfos.update(
  {name:'張三'},
  {$max:

    {age:33}

  }
)

張三的age取大值,由於23<33,因此修改age爲33。若是修改的值比23小,那麼不作操做。
字段操做運算符   $rename  修改filed的名字  db.userinfos.update(

  {name:'張三'},
  {$rename:

    {age:'年齡'}

  }
)

 將張三的age字段名改爲年齡,值不變,年齡=23
$unset  刪除field  db.userinfos.update(

  {name:'張三'},
  {$unset:

    {level:''}

  }
)

 將張三的level字段刪除

 

   數組相關的update運算符:

測試數據:

 db.students.insertMany( [{ "_id" : 1, "grades" : [ 85, 80, 80 ] },    { "_id" : 2, "grades" : [ 88, 90, 92 ] }] )
 數組運算符 $ 單個佔位符

db.students.updateOne(
  { _id: 1, grades: 80 },
  { $set: { "grades.$" : 82 } }
)

修改_id=1的文檔graders中第一個值爲80的元素,值改爲82

結果:

  [{ "_id" : 1, "grades" : [ 85, 82, 80 ] },
  { "_id" : 2, "grades" : [ 88, 90, 92 ] }]

 $[]  全部元素佔位符  

db.students.updateOne(
  { _id: 1},
  { $set: { "grades.$[]" : 100 } }
)

 

修改_id=1的文檔graders中全部元素,值改爲100

結果:

  [{ "_id" : 1, "grades" : [ 100, 100, 100 ] },
  { "_id" : 2, "grades" : [ 88, 90, 92 ] }]

 $[<identifier>]  符合arrayFilter過濾條件的元素佔位符  

db.students.updateOne(
  { _id: 2},
  { $set: { "grades.$[element]" : 100 } },
  { arrayFilters: [ { "element": { $gte: 90 } } ]}
)

 

修改_id=2的文檔graders中大於等於90的元素,值改爲100

結果:

  [{ "_id" : 1, "grades" : [  85, 82, 80  ] },
  { "_id" : 2, "grades" : [ 88, 100, 100 ] }]

 $push  添加元素  

db.students.updateOne(
  { _id: 1 },
  { $push: { "grades" : 98 } }
)

 

在_id=1的文檔graders中添加元素

結果:

  [{ "_id" : 1, "grades" : [  85, 80, 80 ,98 ] },
  { "_id" : 2, "grades" : [ 88, 90, 92 ] }]

$addToSet  添加不存在的元素,若是元素已經存在則無操做  db.students.updateOne(
  { _id: 1 },
  { $addToSet: { "grades" : 100 } }
)
 

在_id=1的文檔graders中添加元素

結果:

  [{ "_id" : 1, "grades" : [  85, 80, 80 ,98,100 ] },
  { "_id" : 2, "grades" : [ 88, 90, 92 ] }]

補充:若是添加的元素是85,由於85已經存在,因此不執行操做

 $pop  彈出(移除)元素  

db.students.updateOne(
  { _id: 1 },
  { $pop: { "grades" : 1 } }
)

 移除最後一個元素

結果:

  [{ "_id" : 1, "grades" : [  85, 80 ] },
  { "_id" : 2, "grades" : [ 88, 90, 92 ] }]

補充:若是{ $pop: { "grades" : -1 } }表示從前邊彈出,移除第一個元素

$pullAll 根據值移除數組中的元素

db.students.update(
  {_id:2},
  {$pullAll:{"grades":[88,90]}}
)

移除_id=2的文檔的graders中值爲88,90的全部元素

結果:

  [{ "_id" : 1, "grades" : [  85, 80, 80  ] },
  { "_id" : 2, "grades" : [ 92 ] }]

 $pull  移除符合條件的元素  

db.students.update(
  {_id:2},
  {$pull:{"grades":{$gt:90}}}
)

 

移除_id=2的文檔的graders中大於90的全部元素

結果:

  [{ "_id" : 1, "grades" : [  85, 80, 80  ] },
  { "_id" : 2, "grades" : [ 88,90 ] }]

  數組批量添加

相關運算符

 $each  和$push,$addToSet配合使用,用於批量添加元素  

db.students.update(
  {_id:1},
  {$push:

    {grades:{$each:[99,100]}}

  }

)

在_id=1的文檔graders中添加元素[99,100]

結果:

  [{ "_id" : 1, "grades" : [  85, 80, 80 ,99,100 ] },
  { "_id" : 2, "grades" : [ 88,90 ,92] }]

 $slice  和$push,$each配合使用,用於限制元素個數  

db.students.update(
  {_id:1},
  {$push:

    {grades:{$each:[99,100],$slice:4}}

  }
)

 在_id=1的文檔graders中添加元素[99,100]

結果:

  [{ "_id" : 1, "grades" : [  85, 80, 80 ,99] },
  { "_id" : 2, "grades" : [ 88,90 ,92] }]

若是使用$slice:-4,則保留後4個元素

$sort 和$push,$each配合使用,在添加元素後進行排序

db.students.update(
  {_id:1},
  {$push:

    {grades:{$each:[70,100],$sort:1}}

  }
)

在_id=1的文檔graders中添加元素[99,100],並排序

結果:

  [{ "_id" : 1, "grades" : [70,80,80,85,100]},
  { "_id" : 2, "grades" : [ 88,90 ,92] }]

若是使用$sort:-1,則倒序排序

$position 和$push,$each配合使用,指定插入元素的位置

db.students.update(
  {_id:1},
  {$push:

    {grades:{$each:[70,100],$position:1}}

  }
)

 在_id=1的文檔graders中,從索引1開始插入元素[99,100]

結果:

  [{ "_id" : 1, "grades" : [85,70,100,80,80]},
  { "_id" : 2, "grades" : [ 88,90 ,92] }]

4.刪除(remove/delete)

  在3.2之前的版本中,mongoDB使用remove方法來刪除文檔,用法以下:

  

  從3.2版本開始,提供了deleteOne()和deleteMany()方法,分別用於刪除單條和多條document,語法以下:

//刪除單條document,功能相似於remove設置justOne:true
  db.userinfos.deleteOne({age:{$gt:25}})
//刪除全部符合條件的document,功能相似於remove設置justOne:false
  db.userinfos.deleteMany({age:{$gt:25}})

  本篇是mongoDB的第一篇,簡單介紹了mongoDB的安裝方法,經過js shell進行mongoDB的CRUD操做,後續會逐步介紹mongoDB的索引、數據聚合、GridFS和C#驅動,以及副本集和sharing集羣搭建。若是本文由錯誤的地方,但願你們能夠指出,我會及時修改,謝謝。

相關文章
相關標籤/搜索