1、MongoDB概念解析:
2、數據庫:
"show dbs"命令可以顯示所有數據的列表。
"db"命令可以顯示當前數據庫對象或集合。
"use"命令,可以連接到一個指定的數據庫。
3、集合:
db.createCollection("mycoll", {capped:true, size:100000})
4、元數據:
5、MongoDB數據類型:
ObjectId
ObjectId
6、創建數據庫:
use DATABASE_NAME
如果數據庫不存在,則創建數據庫,否則切換到指定數據庫。
db.runoob.insert({"name":"菜鳥教程"})
集合只有在內容插入后才會創建
MongoDB 中默認的數據庫為 test,如果你沒有創建新的數據庫,集合將存放在 test 數據庫中。
7、刪除數據庫:
db.dropDatabase()#默認刪除test
db.collection.drop()#刪除集合
-
例子
>use runoob switched to db runoob >show tables site >db.site.drop() true >show tables >
8、創建集合:
db.createCollection(name, options)
-
創建固定集合 mycol,整個集合空間大小 6142800 KB, 文檔最大個數為 10000 個。
>db.createCollection("mycol", {capped: true, autoIndexId: true, size: 6142800, max: 10000})
-
在 MongoDB 中,你不需要創建集合。當你插入一些文檔時,MongoDB 會自動創建集合。
>db.mycol2.insert({"name": "haha"}) >show collections mycol2
9、刪除集合:
db.collection.drop()
#例子
db.mycol2.drop()
10、插入文檔:
db.COLLECTION_NAME.insert(document)
#例子
>db.mycol.insert({title: 'MongoDB教程',
description: 'MongoDB是一個Nosql數據庫',
by: '菜鳥教程',
url: 'http://www.runoob.com',
tags: ['MongoDB', 'database', 'NoSQL'],
likes: 100
})
-
查看已插入文檔:
db.mycol.find()
-
將數據定義成一個變量
> document=({title: 'MongoDB 教程', description: 'MongoDB 是一個 Nosql 數據庫', by: '菜鳥教程', url: 'http://www.runoob.com', tags: ['mongodb', 'database', 'NoSQL'], likes: 100 }); >db.mycol.insert(document) >db.mycol.save(document)
11、更新文檔:
-
update()方法
db.collection.update( <query>, <update>, { upsert: <boolean>, multi: <boolean>, writeConcern: <document> } ) query : update的查詢條件,類似sql update查詢內where后面的。 update : update的對象和一些更新的操作符(如$,$inc...)等,也可以理解為sql update查詢內set后面的 upsert : 可選,這個參數的意思是,如果不存在update的記錄,是否插入objNew,true為插入,默認是false,不插入。 multi : 可選,mongodb 默認是false,只更新找到的第一條記錄,如果這個參數為true,就把按條件查出來多條記錄全部更新。 writeConcern :可選,拋出異常的級別。
-
實例
#將標題“MongoDB教程”改為“MongoDB”。 >db.mycol.update({'title': 'MongoDB教程'}, {$set: {'title': 'MongoDB'}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) # 輸出信息 >db.mycol.find().pretty() { "_id" : ObjectId("56064f89ade2f21f36b03136"), "title" : "MongoDB", "description" : "MongoDB 是一個 Nosql 數據庫", "by" : "菜鳥教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 } > >db.mycol.update({'title': 'MongoDB教程'}, {$set: {'title': 'MongoDB'}}, {multi: true})
-
save()方法
db.collection.save( <document>, { writeConcern: <document> } ) document : 文檔數據。 writeConcern :可選,拋出異常的級別。
-
推薦使用
db.collection.updateOne() #更新單個文檔 db.collection.updateMany() #更新多個文檔
10、刪除文檔:
db.collection.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)
query :(可選)刪除的文檔的條件。
justOne : (可選)如果設為 true 或 1,則只刪除一個文檔。
writeConcern :(可選)拋出異常的級別。
-
實例
> db.col.find() { "_id" : ObjectId("56066169ade2f21f36b03137"), "title" : "MongoDB 教程", "description" : "MongoDB 是一個 Nosql 數據庫", "by" : "菜鳥教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 } { "_id" : ObjectId("5606616dade2f21f36b03138"), "title" : "MongoDB 教程", "description" : "MongoDB 是一個 Nosql 數據庫", "by" : "菜鳥教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 } #移除 >db.mycol.remove({'title': 'MongoDB 教程'}) WriteResult({ "nRemoved" : 2 }) # 刪除了兩條數據 #刪除所有數據 >db.col.remove({}) >db.col.find() >
-
推薦使用
>db.inventory.deleteMany({}) #刪除全部文檔 >db.inventory.deleteMany({status: 'A'}) #刪除status=A的全部文檔 >db.inventory.deleteOne({status: 'D'}) #刪除status=D的一個文檔
11、查詢文檔:
db.collection.find(query, projection)
query :可選,使用查詢操作符指定查詢條件
projection :可選,使用投影操作符指定返回的鍵。查詢時返回文檔中所有鍵值, 只需省略該參數即可(默認省略)。
-
易讀的方式
>db.collection.find().pretty() #格式化顯示所有文檔
-
MongoDB與RDBMS where語句比較:
-
AND條件
>db.collection.find({key1: value1, key2: value2}).pretty() >db.mycol.find({'by': '菜鳥教程', 'title': 'MongoDB 教程'}).pretty()
-
OR條件
>db.collection.find({$or: [{'by': '菜鳥教程'}, {'title': 'MongoDB 教程'}]}).pretty()
-
AND和OR聯合使用
>db.collection.find({'likes': {$gt: 50}, $or: [{'by': '菜鳥教程'}, {'title': 'MongoDB 教程'}]}).pretty()
-
projection參數使用方法
#若不指定 projection,則默認返回所有鍵,指定 projection 格式如下,有兩種模式 db.collection.find(query, {title: 1, by: 1}) // inclusion模式 指定返回的鍵,不返回其他鍵 db.collection.find(query, {title: 0, by: 0}) // exclusion模式 指定不返回的鍵,返回其他鍵
12、條件操作符:
(>) 大于 - $gt greater than
(<) 小于 - $lt less than
(>=) 大于等于 - $gte
-
(<= ) 小于等于 - $lte
db.collection.find({likes: {$gt: 100}}) #Select * from collection where likes >=100; db.collection.find({likes: {$lte: 150}})
-
模糊查詢
#查詢包含“教”字的文檔 db.collection.find({title: /教/}) #查詢以“教”字開頭的文檔 db.collection.find({title: /^教/}) #查詢以“教”字結尾的文檔 db.collection.find({title: /教$/})
13、$type操作符:
#獲取集合中title為字符串的數據
>db.collection.find({'title': {$type: 2}})
>db.collection.find({'title': {$type: 'string'}})
15、Limit與Skip方法:
-
Limit()方法:指定數據記錄的數量
>db.COLLECTION_NAME.find().limit(NUMBER) 舉例 #第一個 {} 放 where 條件,為空表示返回集合中所有文檔。 #第二個 {} 指定那些列顯示和不顯示 (0表示不顯示 1表示顯示)。 >db.collection.find({}, {'title': 1, _id: 0}).limit(2) { "title" : "PHP 教程" } { "title" : "Java 教程" } >
-
Skip()方法:跳過指定數量的數據
>db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER) 舉例 >db.collection.find({}, {'title': 1, _id: 0}).limit(1).skip(1) #skip默認參數為0 { "title" : "Java 教程" } >
-
Limit() 和Skip()聯合舉例
#想要讀取從 10 條記錄后 100 條記錄,相當于 sql 中limit (10,100)。 >db.COLLECTION_NAME.find().skip(10).limit(100) #假設查詢第100001條數據,這條數據的Amount值是:2399927, >db.test.sort({"amount":1}).skip(100000).limit(10) //183ms >db.test.find({amount:{$gt:2399927}}).sort({"amount":1}).limit(10) //53ms >
16、排序Sort()方法:
# 通過使用1和-1來指定排序的方式
>db.COLLECTION_NAME.find().sort({KEY: 1})
#舉例
>db.collection.find({}, {'title': 1, _id: 0}).sort({'likes': -1})
{ "title" : "PHP 教程" }
{ "title" : "Java 教程" }
{ "title" : "MongoDB 教程" }
>
- 注:skip(), limilt(), sort()三個放在一起執行的時候,執行的順序是先 sort(), 然后是 skip(),最后是顯示的 limit()。
17、索引——createIndex()方法
>db.collection.createIndex(keys, options)
#key為需要創建索引字段,1 為指定按升序創建索引
舉例
>db.collection.createIndex({'title': 1})
#使用多個字段創建索引(關系型數據庫中稱作復合索引)
>db.collection.createIndex({'title': 1, 'description': -1})
18、聚合——aggregate()方法
>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
-
集合
{ _id: ObjectId(7df78ad8902c) title: 'MongoDB Overview', description: 'MongoDB is no sql database', by_user: 'runoob.com', url: 'http://www.runoob.com', tags: ['mongodb', 'database', 'NoSQL'], likes: 100 }, { _id: ObjectId(7df78ad8902d) title: 'NoSQL Overview', description: 'No sql database is very fast', by_user: 'runoob.com', url: 'http://www.runoob.com', tags: ['mongodb', 'database', 'NoSQL'], likes: 10 }, { _id: ObjectId(7df78ad8902e) title: 'Neo4j Overview', description: 'Neo4j is no sql database', by_user: 'Neo4j', url: 'http://www.neo4j.com', tags: ['neo4j', 'database', 'NoSQL'], likes: 750 },
-
舉例
#計算每個作者所寫的文章數 >db.collection.aggregate([{$group: {_id: '$by_user', num_tutorial: {$sum: 1}}}]) { "result" : [ { "_id" : "runoob.com", "num_tutorial" : 2 }, { "_id" : "Neo4j", "num_tutorial" : 1 } ], "ok" : 1 } > 類似于 select by_user, count(*) from collection group by by_user
-
管道的概念
聚合框架中常用的幾個操作
1、$project實例
>db.mycol.aggregate(
{$project:{
title: 1,
author: 1,
}});
2、$match實例
#$match用于獲取分數大于70小于或等于90記錄,然后將符合條件的記錄送到下一階段$group管道操作符進行處理。
>db.mycol.aggregate([
{$match: {score: {$gt: 70, $lte: 90}}} ,
{$group: {_id: null, count: {$sum: 1}}}
]);
3、skip實例
>db.mycol.aggregate(
{$skip: 5});
19、MongoDB關系:
1:1
1:N
N:1
N:N
-
嵌入式關系
{"_id":ObjectId("52ffc33cd85242f436000001"), "contact": "987654321", "dob": "01-01-1991", "name": "Tom Benzamin", "address": [ { "building": "22 A, Indiana Apt", "pincode": 123456, "city": "Los Angeles", "state": "California" }, { "building": "170 A, Acropolis Apt", "pincode": 456789, "city": "Chicago", "state": "Illinois" }] } #查詢用戶地址 db.users.findOne({"name": "Tom Benzamin"}, {"address": 1})
-
引用式關系
#通過引用文檔的id字段來建立關系 { "_id":ObjectId("52ffc33cd85242f436000001"), "contact": "987654321", "dob": "01-01-1991", "name": "Tom Benzamin", "address_ids": [ ObjectId("52ffc4a5d85242602e000000"), ObjectId("52ffc4a5d85242602e000001") ] } #這種方法需要兩次查詢: #第一次查詢用戶地址的對象id; #第二次通過查詢的id獲取用戶的詳細地址信息。 >var result = db.users.findOne({"name": "Tom Benzamin"}, {"address_ids": 1}) >var addresses = db.address.find({"_id": {"$in": result["address_ids"]}})
20、數據庫引用:
-
使用DBRefs
{$ref: , $id: , $db: }
id:引用的id
$db:數據庫名稱,可選參數
{ "_id":ObjectId("53402597d852426020000002"),
"address": {
"$ref": "address_home",
"$id": ObjectId("534009e4d852427820000002"),
"$db": "runoob"
},
"contact": "987654321",
"dob": "01-01-1991",
"name": "Tom Benzamin"
}
#通過指定$ref參數(address_home集合)來查找集合中指定id的用戶地址信息
>var user = db.users.findOne({"name": "Tom Benzamin"})
>var dbRef = user.address
>db[dbRef.$ref].findOne({"_id": (dbRef.$id)})
#返回結果
{
"_id" : ObjectId("534009e4d852427820000002"),
"building" : "22 A, Indiana Apt",
"pincode" : 123456,
"city" : "Los Angeles",
"state" : "California"
}
21、查詢分析:
-
使用explain()
#在集合中創建索引 >db.users.ensureIndex({gender: 1, user_name: 1}) >db.users.find({gender: "M"}, {user_name: 1, _id: 0}).explain() #查詢結果 { "cursor" : "BtreeCursor gender_1_user_name_1", "isMultiKey" : false, "n" : 1, "nscannedObjects" : 0, "nscanned" : 1, "nscannedObjectsAllPlans" : 0, "nscannedAllPlans" : 1, "scanAndOrder" : false, "indexOnly" : true, "nYields" : 0, "nChunkSkips" : 0, "millis" : 0, "indexBounds" : { "gender" : [ [ "M", "M" ] ], "user_name" : [ [ { "$minElement" : 1 }, { "$maxElement" : 1 } ] ] } }
indexOnly: 字段為 true ,表示我們使用了索引。
cursor:因為這個查詢使用了索引,MongoDB 中索引存儲在B樹結構中,所以這是也使用了 BtreeCursor 類型的游標。如果沒有使用索引,游標的類型是 BasicCursor。這個鍵還會給出你所使用的索引的名稱,你通過這個名稱可以查看當前數據庫下的system.indexes集合(系統自動創建,由于存儲索引信息,這個稍微會提到)來得到索引的詳細信息。
n:當前查詢返回的文檔數量。
nscanned/nscannedObjects:表明當前這次查詢一共掃描了集合中多少個文檔,我們的目的是,讓這個數值和返回文檔的數量越接近越好。
millis:當前查詢所需時間,毫秒數。
indexBounds:當前查詢具體使用的索引。
-
使用hint()
使用hint來強制MongoDB使用一個指定的索引。#如下查詢實例指定了使用 gender 和 user_name 索引字段來查詢: >db.users.find({gender: "M"}, {user_name: 1, _id: 0}).hint({gender: 1, user_name: 1}) #可以使用 explain() 函數來分析以上查詢: >db.users.find({gender:"M"},{user_name:1,_id:0}).hint({gender:1,user_name:1}).explain()
22、原子操作:
原子操作常用命令:
-
$set:用來指定一個鍵并更新鍵值,若鍵不存在則創建
{ $set : { field : value } }
-
$unset:用來刪除一個鍵。
{ $unset : { field : 1} }
-
$inc:可以對文檔的某個值為數字型(只能為滿足要求的數字)的鍵進行增減的操作。
{ $inc : { field : value } }
-
$push:把value追加到field里面去,field一定要是數組類型才行,如果field不存在,會新增一個數組類型加進去。
{ $push : { field : value } }
-
$pushAll:一次可以追加多個值到一個數組字段內。
{ $pushAll : { field : value_array } }
-
$pull:從數組field內刪除一個等于value值。
{ $pull : { field : _value } }
$addToSet:增加一個值到數組內,而且只有當這個值不在數組內才增加。
-
$pop:刪除數組的第一個或最后一個元素
{ $pop : { field : 1 } }
-
$rename:修改字段名稱
{ $rename : { old_field_name : new_field_name } }
-
$bit:位操作,integer類型
{$bit : { field : {and : 5}}}
舉例
> t.find()
{ "_id" : ObjectId("4b97e62bf1d8c7152c9ccb74"), "title" : "ABC", "comments" : [ { "by" : "joe", "votes" : 3 }, { "by" : "jane", "votes" : 7 } ] }
> t.update( {'comments.by':'joe'}, {$inc:{'comments.$.votes':1}}, false, true )
> t.find()
{ "_id" : ObjectId("4b97e62bf1d8c7152c9ccb74"), "title" : "ABC", "comments" : [ { "by" : "joe", "votes" : 4 }, { "by" : "jane", "votes" : 7 } ] }
23、高級索引:
{
"address": {
"city": "Los Angeles",
"state": "California",
"pincode": "123"
},
"tags": [
"music",
"cricket",
"blogs"
],
"name": "Tom Benzamin"
}
-
索引數組字段
>db.users.ensureIndex({"tags": 1}) #創建索引后,檢索集合的tags字段 >db.users.find({tags: "music"}) >db.users.find({tags: "music"}).explain()
-
索引子文檔字段
>db.users.ensureIndex({"address.city": 1, "address.state": 1, "address.pincode": 1}) >db.users.find({"address.city": "Los Angeles"}) >db.users.find({"address.state":"California","address.city":"Los Angeles"}) >
24、ObjectId:
-
ObjectId格式:
前4個字節表示時間戳
接下來的3個字節是機器標識碼
緊接的兩個字節由進程id組成(PID)
最后三個字節是隨機數#創建新的ObjectId >newObjectId = ObjectId() ObjectId("5349b4ddd2781d08c09890f3") #創建文檔的時間戳 >ObjectId("5349b4ddd2781d08c09890f4").getTimestamp() #返回文檔創建時間 ISODate("2014-04-12T21:49:17Z") #ObjectId轉換為字符串 >new ObjectId().str #返回Guid格式的字符串 5349b4ddd2781d08c09890f3
25、Map Reduce:
-
MapReduce基本語法:
>db.collection.mapReduce( function() {emit(key, value);}, //map函數 function(key, values) {return reduceFunction}, //reduce函數 { out: collection, query: document, sort: document, limit: number } )
注:使用 MapReduce 要實現兩個函數 Map 函數和 Reduce 函數,Map 函數調用 emit(key, value),遍歷 collection 中所有的記錄,將 key 與 value 傳遞給 Reduce 函數進行處理。
參數說明
**map **:映射函數 (生成鍵值對序列,作為 reduce 函數參數)。
reduce:統計函數,reduce函數的任務就是將key-values變成key-value,也就是把values數組變成一個單一的值value。。
out:統計結果存放集合 (不指定則使用臨時集合,在客戶端斷開后自動刪除)。
query:一個篩選條件,只有滿足條件的文檔才會調用map函數。(query,limit,sort可以隨意組合)
sort:和limit結合的sort排序參數(也是在發往map函數前給文檔排序),可以優化分組機制
limit:發往map函數的文檔數量的上限(要是沒有limit,單獨使用sort的用處不大)-
舉例
在集合 orders 中查找 status:"A" 的數據,并根據 cust_id 來分組,并計算 amount 的總和。
>db.posts.mapReduce( function() { emit(this.user_name,1); }, function(key, values) {return Array.sum(values)}, { query:{status:"active"}, out:"post_total" } ) #輸出結果 { "result" : "post_total", "timeMillis" : 23, "counts" : { "input" : 5, "emit" : 5, "reduce" : 1, "output" : 2 }, "ok" : 1 }
未完待續...