MongoDB的基本用法

1 前言

MongoDB是一個基於分佈式文件存儲的開源數據庫系統。mongodb

MongoDB 將數據存儲爲一個文檔,數據結構由鍵值(key=>value)對組成。MongoDB 文檔相似於 JSON 對象。字段值能夠包含其餘文檔,數組及文檔數組。數據庫

2 安裝(mac)

  • 安裝homebrew
  • 使用brew安裝mongodb
brew install mongodb
複製代碼
  • 可視化工具 Robomongo

3 mongodb啓動與鏈接(mac)

3.1 服務端啓動

3.1.1 啓動步驟

    1. 在要啓動的目錄下新建一個目錄(如:data
mkdir data
複製代碼
    1. 命令行中輸入(--dbpath參數指定數據庫路徑)
mongod --dbpath='./data'
複製代碼

若是出現waiting for connections on port 27017就表示啓動成功。express

注意:這個命令窗體絕對不能關,關閉這個窗口就至關於中止了mongodb服務json

3.1.2 mongod啓動命令mongod參數說明

選項 含義
--port 指定服務端口號,默認端口27017
--logpath 指定MongoDB日誌文件,注意是指定文件不是目錄
--logappend 使用追加的方式寫日誌
--dbpath 指定數據庫路徑
--directoryperdb 設置每一個數據庫將被保存在一個單獨的目錄

3.2 客戶端啓動

  • 命令行輸入
mongo
複製代碼

也能夠設置host數組

mongo --host 127.0.0.1
複製代碼

4 MongoDB基本概念

  • 數據庫 MongoDB的單個實例能夠容納多個獨立的數據庫,好比一個學生管理系統就能夠對應一個數據庫實例。
  • 集合 數據庫是由集合組成的,一個集合用來表示一個實體,如學生集合。
  • 文檔 集合是由文檔組成的,一個文檔表示一條記錄,好比一位同窗張三就是一個文檔

對應關係以下圖: bash

對應關係

5 數據庫操做

5.1 查看全部數據庫

show dbs
複製代碼

返回以下:數據結構

admin       0.000GB
book        0.000GB
leave       0.000GB
local       0.000GB
page        0.000GB
school        0.000GB
students    0.000GB
複製代碼

5.2 使用數據庫

實例 切換到 school數據庫下:app

use school
複製代碼

返回以下:less

switched to db school
複製代碼

注:若是此數據庫存在,則切換到此數據庫下,若是此數據庫還不存在也能夠切過來分佈式

注: 咱們剛建立的數據庫school若是不在列表內,要顯示它,咱們須要向school數據庫插入一些數據

db.school.insert({name:'爲民小學',age:10});
複製代碼

5.3 查看當前使用的數據庫

db 或 db.getName()
複製代碼

5.4 刪除數據庫

db.dropDatabase()
複製代碼

返回以下:

{ "dropped" : "school", "ok" : 1 }
複製代碼

6 集合操做

6.1 查看集合幫助

db.school.help()
複製代碼

返回以下:

BCollection help
	db.school.find().help() - show DBCursor help
	db.school.bulkWrite( operations, <optional params> ) - bulk execute write ...
複製代碼

6.2 查看數據庫下的集合

show collections
複製代碼

返回以下:

grade1
grade2
複製代碼

6.3 建立集合

  • 建立一個空集合(db.createCollection(collection_Name))
db.createCollection('grade3')
複製代碼

返回以下:

{ "ok" : 1 }
複製代碼
  • 建立集合並插入一個文檔(db.collection_Name.insert(document))
db.grade1.insert({name: 'Lily', age: 8})
複製代碼

返回以下:

WriteResult({ "nInserted" : 1 })
複製代碼

7 文檔操做

7.1 插入文檔

insert

  • db.collection_name.insert(document)
db.grade1.insert({name: 'Tom', age: 9})
複製代碼

note:每當插入一條新文檔的時候mongodb會自動爲此文檔生成一個_id屬性,_id必定是惟一的,用來惟一標識一個文檔 _id也能夠直接指定,但若是數據庫中此集合下已經有此_id的話插入會失敗。

{
    "_id" : ObjectId("5addbfbb163098017a6a72ed"),
    "name" : "Tom",
    "age" : 9.0
}
複製代碼

save

  • db.collection_name.save(document)

note:若是不指定 _id 字段 save() 方法相似於 insert() 方法。若是指定 _id 字段,則會更新該 _id 的數據。

// insert
db.grade1.insert({_id: '1',name: 'Han Meimei', age: 8})// WriteResult({ "nInserted" : 1 })

// 存在{_id:1},則更新 _id爲1的document
db.grade1.save({_id: '1',name: 'Han Meimei', age: 9})// WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

// 不存在{_id:2},則插入一條新文檔
db.grade1.save({_id: '2',name: 'Han Meimei', age: 9})// WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : "2" })
複製代碼

執行腳本插入

mongo exc_js/1.js
> load exc_js/1.js
複製代碼

7.2 更新文檔

7.2.1 語法 & 參數說明

db.collection.update(
   <query>,
   <updateObj>,
   {
     upsert: <boolean>,
     multi: <boolean>
   }
)
複製代碼
  • query 查詢條件,指定要更新符合哪些條件的文檔
  • update 更新後的對象或指定一些更新的操做符
    • $set直接指定更新後的值
    • $inc在原基礎上累加
  • upsert 可選,這個參數的意思是,若是不存在符合條件的記錄時是否插入updateObj. 默認是false,不插入。
  • multi 可選,mongodb 默認只更新找到的第一條記錄,若是這個參數爲true,就更新全部符合條件的記錄。

7.2.2 操做符

(1) $inc

{ $inc: { <field1>: <amount1>, <field2>: <amount2>, ... } }

  • 在原基礎上累加(increment)
// 給 {name: 'Tom'} 的文檔的age累加 10
db.grade1.update({name: 'Tom'}, {$inc: {age:10}})
// WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
複製代碼

(2) $push

{ $push: { <field1>: <value1>, ... } }

  • 向數組中添加元素
db.grade1.update({name:'Tom'}, {$push: {'hobby':'reading'} })
// WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
// { "_id" : ObjectId("5addbfbb163098017a6a72ed"), "name" : "Tom", "hobby" : [ "reading" ] }

// 不會覆蓋已有的
db.grade1.update({name:'Tom'}, {$push: {'hobby':'reading'} })
// WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
// { "_id" : ObjectId("5addbfbb163098017a6a72ed"), "name" : "Tom", "hobby" : [ "reading", "reading" ] }

複製代碼

(3) $addToSet

{ $addToSet: { <field1>: <value1>, ... } }

  • 給數組添加或者設置一個值,
  • 有 - do nothing, 沒有 - 添加
// /第一次沒有 huge
db.grade1.update({_id:3}, {$addToSet: {friends:'huge'}})
// WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })


// 第二次 有 huge
db.grade1.update({_id:3}, {$addToSet: {friends:'huge'}})
// WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
複製代碼

(4) $pop

{ $pop: { <field>: <-1 | 1>, ... } }

  • 刪除數組的第一個或者最後一個元素。
  • 傳入1刪除最後一個元素
  • 傳入-1刪除第一個元素
db.grade1.update({_id:3}, {$pop:{friends: 1}})
// WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

db.grade1.update({_id:3}, {$pop:{friends: -1}})
// WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
複製代碼

(5) $each

{ $addToSet: { <field>: { $each: [ <value1>, <value2> ... ] } } }

  • Use with the $addToSet operator to add multiple values to an array if the values do not exist in the .
db.grade1.update({_id:3}, {$addToSet:{friends:{$each: ['huangbo','zhangyixing']}}})
//WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

// 已經有的時候就不會再添加了
db.grade1.update({_id:3}, {$addToSet:{friends:{$each: ['huangbo','zhangyixing']}}})
//WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
複製代碼

{ $push: { <field>: { $each: [ <value1>, <value2> ... ] } } }

  • Use with the $push operator to append multiple values to an array .
db.grade1.update({_id:3}, {$push:{friends:{$each: ['huangbo','zhangyixing']}}})
// WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
複製代碼

$addToSet中使用時,如有則忽略,若沒有則添加。在$push中使用時,無論有沒有都會添加。

(6) $ne

{field: {$ne: value} }

  • not equal
// 給 name爲'Han Meimei' && hobby中不等於'reading' && _id不等於'2'的文檔 的hobby 屬性 添加一個 'drinking'
db.grade1.update({name: 'Han Meimei', hobby:{$ne:'reading'}, _id: {$ne:'2'}}, {$push: {hobby: 'drinking'}})
// WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
複製代碼

(7)$set

{ $set: { <field1>: <value1>, ... } }

  • 設置字段的第一層的值(Set Top-Level Fields)
  • 設置嵌套字段的值 (Set Fields in Embedded Documents)
  • 修改指定索引元素
/* 原來的數據: {_id:3, info:{id: '11'}, friends:['liudehua', 'zhourunfa']} */
/*設置字段的第一層的值(Set Top-Level Fields)*/ 
db.grade1.update({_id:3}, {$set:{"info11":{id:'11'}}})
// WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })


/*設置嵌套字段的值 (Set Fields in Embedded Documents)*/
db.grade1.update({_id:3}, {$set:{"info.id":'22'}})
// WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

/*修改指定索引元素*/
db.grade1.update({_id:3}, {$set:{"friends.1":'zhangmanyu'}})
// WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
複製代碼

(8) $unset

{ $unset: { <field1>: "", ... } }

  • 刪除指定的鍵
// 把 {name: 'Tom'} 的文檔中的 age 鍵給刪除掉
db.grade1.update({name: 'Tom'}, {$unset:{'age':''}})
// WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
/* { "_id" : ObjectId("5addbfbb163098017a6a72ed"), "name" : "Tom" }*/
複製代碼

7.3 刪除文檔

  • remove方法是用來移除集合中的數據

語法

db.collection.remove(
   <query>,
   {
     justOne: <boolean>
   }
)
複製代碼

參數說明

query :(可選)刪除的文檔的條件。
justOne : (可選)若是設爲 true 或 1,則只刪除匹配到的多個文檔中的第一個。默認爲 true
複製代碼
/*{justOne:true} 值刪除匹配到的第一條文檔*/
db.grade1.remove({'name': 'Han Meimei'}, {justOne: true})
// WriteResult({ "nRemoved" : 1 })

/*刪除匹配到的全部文檔*/
db.grade1.remove({'name': 'Han Meimei'})
// WriteResult({ "nRemoved" : 2 })

複製代碼

7.4 查詢文檔

7.4.1

語法

db.collection_name.find(query, projection);
複製代碼

參數

query       - 使用查詢操做符指定選擇過濾器
projection  - 指定配到到的文檔中的返回的字段。
複製代碼
/*projection*/
{ field1: <value>, field2: <value> ... }

/*value:*/
1 or true: 在返回的文檔中包含這個字段
0 or false:在返回的文檔中排除這個字段 
複製代碼

note: _id字段默認一直返回,除非手動將_id字段設置爲0false

舉個栗子

//查詢grade1下全部的文檔
db.grade1.find()
複製代碼

7.4.2 findOne()

  • 只返回匹配到的第一條文檔

7.4.3 查詢操做符

(1) $in

  • Matches any of the values specified in an array.
  • (在數組範圍內的)
//原始數據():
{ "_id" : 1, "name" : "Tom1", "age" : 9 }
{ "_id" : 2, "name" : "Tom2", "age" : 15 }
{ "_id" : 3, "name" : "Tom3", "age" : 11 }
複製代碼
db.grade1.find({age:{$in:[9,11]}})
// { "_id" : 1, "name" : "Tom1", "age" : 9 }
// { "_id" : 3, "name" : "Tom3", "age" : 11 }
複製代碼

(2) $nin

  • Matches none of the values specified in an array.
db.grade1.find({age:{$nin:[9,11]}})
// { "_id" : 2, "name" : "Tom2", "age" : 15 }
複製代碼

(3) $not

  • Inverts the effect of a query expression and returns documents that do not match the query expression.
db.grade1.find({age:{$not:{$lt:11}}})
//{ "_id" : 2, "name" : "Tom2", "age" : 15 }
//{ "_id" : 3, "name" : "Tom3", "age" : 11 }
複製代碼

(4) $gt

  • Matches values that are greater than a specified value.
  • 大於

(5) $gte

  • Matches values that are greater than or equal to a specified value.
  • 大於等於

(6) $lt

  • Matches values that are less than a specified value.
  • 小於

(7) $lte

  • Matches values that are less than or equal to a specified value.
  • 小於等於

(8)$ne

  • Matches all values that are not equal to a specified value.
  • 不等於
db.grade1.find({age:{$ne:9}})
// { "_id" : 2, "name" : "Tom2", "age" : 15 }
// { "_id" : 3, "name" : "Tom3", "age" : 11 }
複製代碼

7.4.4 數組的用法

// 原始數據
{ "_id" : 1, "name" : "Tom1", "age" : 9, "friends" : [ "Lily", "Jobs", "Lucy", "Zhang San" ] }
{ "_id" : 2, "name" : "Tom2", "age" : 15, "friends" : [ "Zhange San", "Li Si" ] }
{ "_id" : 3, "name" : "Tom3", "age" : 11, "friends" : [ "Zhange San", "Lily" ] }
複製代碼
db.grade1.find({"friends" : [ "Lily", "Jobs", "Lucy", "Zhang San" ]})
// { "_id" : 1, "name" : "Tom1", "age" : 9, "friends" : [ "Lily", "Jobs", "Lucy", "Zhang San" ] }

db.grade1.find({"friends" : [ "Lily" ]})
// 空

// $all
db.grade1.find({"friends" :{$all: ["Zhang San"]}})
// { "_id" : 1, "name" : "Tom1", "age" : 9, "friends" : [ "Lily", "Jobs", "Lucy", "Zhang San" ] }

// $in
db.grade1.find({"friends" :{$in: ["Zhang San"]}})
{ "_id" : 1, "name" : "Tom1", "age" : 9, "friends" : [ "Lily", "Jobs", "Lucy", "Zhang San" ] }

// $size
db.grade1.find({"friends" :{$size:4}})
//{ "_id" : 1, "name" : "Tom1", "age" : 9, "friends" : [ "Lily", "Jobs", "Lucy", "Zhang San" ] }

// $slice
db.collection.find( { field: value }, { array: {$slice: count } } );
> db.grade1.find({"friends" :{$size:4}}, {"friends":{$slice:2}})
//{ "_id" : 1, "name" : "Tom1", "age" : 9, "friends" : [ "Lily", "Jobs" ] }
複製代碼

7.4.5 $where

  • $where能夠接收兩種參數傳遞給查詢系統,一種是包含JavaScript表達式的字符串,另一種是JavaScript函數。

  • $where很是靈活,可是它須要數據庫集合中的每個文檔中處理這個JavaScript表達式或者JavaScript函數,因此會比較慢。

  • 在JavaScript表達式或者JavaScript函數中引用文檔的時候,但是使用this或者obj

// 數據庫數據
{ "_id" : 1, "name" : "Tom1", "age" : 9, "friends" : [ "Lily", "Jobs", "Lucy", "Zhang San" ] }
{ "_id" : 2, "name" : "Tom2", "age" : 15, "friends" : [ "Zhange San", "Li Si" ] }
{ "_id" : 3, "name" : "Tom3", "age" : 11, "friends" : [ "Zhange San", "Lily" ] }

// JS表達式的字符串
> db.grade1.find({$where:'this.name == "Tom1"'})
//{ "_id" : 1, "name" : "Tom1", "age" : 9, "friends" : [ "Lily", "Jobs", "Lucy", "Zhang San" ] }

// 函數
> db.grade1.find({$where: function(){return this.age == 9}})
// { "_id" : 1, "name" : "Tom1", "age" : 9, "friends" : [ "Lily", "Jobs", "Lucy", "Zhang San" ] }

複製代碼

7.4.6 Cursor Methods

這些方法改變了執行基礎查詢方式。

包括cursor.forEach()cursor.map()cursor.limit()cursor.size()cursor.count()等。

// forEach舉例
> var result = db.grade1.find({$where: function(){return this.age >= 9}});
> result.forEach(elem => printjson(elem))
/*{ "_id" : 1, "name" : "Tom1", "age" : 9, "friends" : [ "Lily", "Jobs", "Lucy", "Zhang San" ] } { "_id" : 2, "name" : "Tom2", "age" : 15, "friends" : [ "Zhange San", "Li Si" ] } { "_id" : 3, "name" : "Tom3", "age" : 11, "friends" : [ "Zhange San", "Lily" ] }*/
複製代碼

8 條件操做符

8.1 條件操做符

  • $gt - 大於
  • $gte- 大於等於
  • $lt - 小於
  • $lte - 小於等於
// 大於等於
db.grade1.find({age:{$gte:9}})
/*{ "_id" : 1, "name" : "Tom1", "age" : 9, "friends" : [ "Lily", "Jobs", "Lucy", "Zhang San" ] } { "_id" : 2, "name" : "Tom2", "age" : 15, "friends" : [ "Zhange San", "Li Si" ] } { "_id" : 3, "name" : "Tom3", "age" : 11, "friends" : [ "Zhange San", "Lily" ] }*/

// 大於等於9 而且 小於等於13
db.grade1.find({age:{$gte:9}, age: {$lte:13}})
/*{ "_id" : 1, "name" : "Tom1", "age" : 9, "friends" : [ "Lily", "Jobs", "Lucy", "Zhang San" ] } { "_id" : 3, "name" : "Tom3", "age" : 11, "friends" : [ "Zhange San", "Lily" ] }*/

複製代碼

8.2 使用_id進行查詢

//原始數據
{ "_id" : ObjectId("5ae1b6e3e4366d57f3307239"), "name" : "Tom4" }

> db.grade1.find({_id: '5ae1b6e3e4366d57f3307239'}).count()
// 0
> db.grade1.find({_id:ObjectId('5ae1b6e3e4366d57f3307239')}).count()
// 1

複製代碼

count() 查詢結果的條數

8.3 正則匹配

db.collection.find({key:/value/})

// name是以`T`開頭的數據
db.grade1.find({name: /^T/})
/*{ "_id" : 1, "name" : "Tom1", "age" : 9, "friends" : [ "Lily", "Jobs", "Lucy", "Zhang San" ] } { "_id" : 2, "name" : "Tom2", "age" : 15, "friends" : [ "Zhange San", "Li Si" ] } { "_id" : 3, "name" : "Tom3", "age" : 11, "friends" : [ "Zhange San", "Lily" ] } { "_id" : ObjectId("5ae1b6e3e4366d57f3307239"), "name" : "Tom4" }*/
複製代碼

9 與和或

9.1 and

db.collection_name.find({field1: value1, field2:value2})

//原始數據
{ "_id" : 1, "name" : "Tom1", "age" : 9, "friends" : [ "Lily", "Jobs", "Lucy", "Zhang San" ] }
{ "_id" : 2, "name" : "Tom2", "age" : 15, "friends" : [ "Zhange San", "Li Si" ] }
{ "_id" : 3, "name" : "Tom3", "age" : 11, "friends" : [ "Zhange San", "Lily" ] }
複製代碼
// and name是以‘T’開頭 而且 age是9 的數據
> db.grade1.find({name: /^T/, age: 9})
// { "_id" : 1, "name" : "Tom1", "age" : 9, "friends" : [ "Lily", "Jobs", "Lucy", "Zhang San" ] }
複製代碼

9.2 or

db.collection_name.find({ $or: [{key1: value1}, {key2:value2} ] })

// name 是Tom1 或者 age是11 的數據
> db.grade1.find({$or:[{name: 'Tom1'}, {age: 11}]})
/*{ "_id" : 1, "name" : "Tom1", "age" : 9, "friends" : [ "Lily", "Jobs", "Lucy", "Zhang San" ] } { "_id" : 3, "name" : "Tom3", "age" : 11, "friends" : [ "Zhange San", "Lily" ] }*/
複製代碼

9.3 and 和 all 聯合使用

> db.grade1.find({age: 9,$or:[{name: 'Tom1'}, {age: 11}]})
/*{ "_id" : 1, "name" : "Tom1", "age" : 9, "friends" : [ "Lily", "Jobs", "Lucy", "Zhang San" ] }*/
複製代碼

10 分頁查詢

10.1 limit

  • 讀取指定數量的數據記錄 語法

db.collectoin_name.find().limit(number)

10.2 skip

  • 跳過指定數量的數據

db.collectoin_name.find().skip(number)

10.3 sort

-經過參數指定排序的字段,並使用 1 和 -1 來指定排序的方式,其中 1爲升序排列,而-1是用於降序排列。

db.collectoin_name.find().sort({field:1})

db.collectoin_name.find().sort({field:-1})

10.4 分頁

// 原始數據爲 1 2 3 4 5 6 7 8 9

> var pageIndex = 3;
> var pageSize = 3;
> var res = db.grade1.find({}).skip((pageIndex - 1) * pageSize).limit(pageSize).sort({username: 1});
> res
/*{ "_id" : ObjectId("5ae1cbc609f3ac9a41442546"), "username" : "Lily_7", "password" : 7 } { "_id" : ObjectId("5ae1cbc609f3ac9a41442547"), "username" : "Lily_8", "password" : 8 } { "_id" : ObjectId("5ae1cbc609f3ac9a41442548"), "username" : "Lily_9", "password" : 9 }*/

var res1 = db.grade1.find().skip((pageIndex - 1) * pageSize).limit(pageSize).sort({username: -1});
/*{ "_id" : ObjectId("5ae1cbc609f3ac9a41442542"), "username" : "Lily_3", "password" : 3 } { "_id" : ObjectId("5ae1cbc609f3ac9a41442541"), "username" : "Lily_2", "password" : 2 } { "_id" : ObjectId("5ae1cbc609f3ac9a41442540"), "username" : "Lily_1", "password" : 1 }*/
複製代碼

note: 沒有前後順序

11 ObjectId構成

以前咱們使用MySQL等關係型數據庫時,主鍵都是設置成自增的。但在分佈式環境下,這種方法就不可行了,會產生衝突。爲此,MongoDB採用了一個稱之爲ObjectId的類型來作主鍵。ObjectId是一個12字節的 BSON 類型字符串。按照字節順序,一次表明:

  • 4字節:UNIX時間戳
  • 3字節:表示運行MongoDB的機器
  • 2字節:表示生成此_id的進程
  • 3字節:由一個隨機數開始的計數器生成的值

12 參考

相關文章
相關標籤/搜索