MongoDB使用總結(jié)
數(shù)據(jù)庫操作
-
show dbs: 顯示所有的數(shù)據(jù)庫 -
use user: 選擇數(shù)據(jù)庫user,如果這個數(shù)據(jù)庫存在,那么就使用,不存在就新建,但是此時的數(shù)據(jù)庫中根本不存在數(shù)據(jù),因此使用show dbs不能顯示該數(shù)據(jù)庫 -
db.dropDatabase(): 刪除數(shù)據(jù)庫,其中的db表示當(dāng)前數(shù)據(jù)庫
集合操作(表)
- 在MongoDB中,數(shù)據(jù)庫中的集合相當(dāng)于SQL中的表,一個數(shù)據(jù)庫中可以存在多個集合,每一個集合都是一個JSON文檔形式的存儲
-
show tables: 顯示所有的集合 -
show collections: 顯示所有的集合
創(chuàng)建集合
db.createCollection(name, options)- 文檔
刪除集合
-
db.collection.drop()-
db.user.drop(): 刪除user集合
-
文檔操作
- 一個集合中可以包含多條文檔,一個文檔就相當(dāng)于SQL中的一條數(shù)據(jù),這里的文檔是JSON格式的文檔
插入文檔
-
db.collectionName.insert(JSON)-
db.user.insert({name:"陳加兵",age:22}): 向user集合中插入一條文檔,如果這個user集合不存在,那么就會新建一個,這個方法默認會為我們插入一個_id
-
更新文檔
update() 方法用于更新已存在的文檔。語法格式如下:
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
參數(shù)說明:
- query : update的查詢條件,類似sql update查詢內(nèi)where后面的。
-
update : update的對象和一些更新的操作符(如
inc...)等,也可以理解為sql update查詢內(nèi)set后面的
- upsert : 可選,這個參數(shù)的意思是,如果不存在update的記錄,是否插入objNew,true為插入,默認是false,不插入。
- multi : 可選,mongodb 默認是false,只更新找到的第一條記錄,如果這個參數(shù)為true,就把按條件查出來多條記錄全部更新。
- writeConcern :可選,拋出異常的級別。
實例
-
db.user.update({name:"jack"},{$set:{name:"tom"}}):相當(dāng)于sql語句中的update user set name="tom" where name="jack",不過這里默認只是更新一條 -
db.user.update({name:"陳加兵"},{$set:{name:"鄭元梅"}},{multi:true}): 更新所有的數(shù)據(jù) -
db.user.update({name:"陳加兵"},{$set:{name:"鄭元梅"}},{upsert:true}): 更新數(shù)據(jù),如果不存在就插入 - 這里的query條件也是可以使用邏輯比較的,比如
age>12,后續(xù)在講到查詢文檔的時候會詳細描述
刪除文檔
- 刪除格式,默認是刪除多條,但是我們可以設(shè)置
justone : true或者justone:1即可刪除一條數(shù)據(jù)
db.collection.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)
-
db.user.remove({name:"陳加兵"}): 刪除全部name=陳加兵的文檔 -
db.user.remove({}): 刪除集合user中的全部文檔 -
db.user.remove({}): 刪除全部文檔,因為這里沒有條件 -
db.user.remove({name:"陳加兵"},{justone:true}): 只刪除一條文檔
查詢文檔
db.collection.findOne(query,projection): 只顯示滿足條件的一條文檔-
格式:
db.collection.find(query,projection): 查詢滿足條件的全部文檔-
query:可選, 查詢的條件,相當(dāng)于where子句 -
projection: 可選,使用投影操作符指定返回的鍵。查詢時返回文檔中所有鍵值, 只需省略該參數(shù)即可(默認省略)
-
插入數(shù)據(jù)(準備)
db.user.insert({name:"Jack",age:22})
db.user.insert({name:"Tom",age:40})
db.user.insert({name:"Mary",age:25})
db.user.insert({name:"Lucy",age:22})
查詢?nèi)?/h4>
-
db.user.find().pretty() : 這里沒有指定查詢條件,那么就是查詢?nèi)?/li>
指定顯示字段
- 默認顯示全部的字段,但是我們可以指定
projection來顯示指定的字段
-
inclusion模式,指定返回的鍵,比如db.user.find({},{name:1}),這里只會顯示_id和name這兩個字段,其他的字段都是不會顯示的
-
exclusion模式,指定不反回的鍵,比如db.user.find({},{name:0}) : 這里只會顯示age和_id,只有name不顯示
- 兩種模式不可以混用,比如
db.user.find({},{name:1,age:0}) ,這個是不可以的
指定查詢條件
-
db.user.find({name:"Jack"}) : 查詢name=Jack的全部文檔內(nèi)容
-
db.user.find({name:"Jack"},{name:0}) : 不顯示name字段
AND條件
-
db.user.find({name:"Jack",age:22}) : 查詢name=Jack并且age=22的文檔信息
-
db.user.find({$and:[{expression1},{expression2},{experssion3},......]})
-
db.user.find({$and:[{name:"Jack"},{age:22}]}) : 和上面一樣的效果
OR 條件
-
db.user.find({$or:[{expression1},{expression2},{expression3}......]})
-
db.user.find({$or:[{name:"Jack"},{age:25}]}) : 查找name=Jack或者age=25的文檔信息
AND 和 OR 聯(lián)合使用
-
db.user.find({name:"Jack",$or:[{_id:1},{age:22}]}) : 查找name=Jack and (_id=1 or age=22)
條件操作符
(>) 大于 - $gt
(<) 小于 - $lt
(>=) 大于等于 - $gte
(<= ) 小于等于 - $lte
(!=) 不等于 - $ne
實例
-
db.user.find({age:{$gt:22}}) : 查找 age>22的信息
-
db.user.find({age:{$gte:22},name:"Jack"}) : 查找age>=22 and name=Jack的信息
limit
- 指定顯示記錄的條數(shù)
-
db.user.find().limit(2) : 只顯示兩條記錄
db.user.find({name:"Jack"}).limit(2)
skip
- 跳過的條數(shù)
-
db.user.find().skip(10) : 跳過前面的十條記錄,顯示后面的
分頁查詢
- 顯示第三頁,每頁顯示10條信息,相當(dāng)于SQL中的
select * from user limit 20,5
db.user.find().skip(20).limit(5)
sort 排序
- 在MongoDB中使用使用
sort()方法對數(shù)據(jù)進行排序,sort()方法可以通過參數(shù)指定排序的字段,并使用 1 和 -1 來指定排序的方式,其中1 為升序排列,而-1是用于降序排列。
db.collection.find().sort({key:1})
-
db.user.find().sort({age:-1}) : 按照age降序排列
-
db.user.find({},{name:1,age:1}).sort({age:-1,name:1}) : 按照name升序,age降序排列
limit,skip,sort執(zhí)行順序
- 執(zhí)行順序為:
sort() --- > skip() ----> limit() ,這個相當(dāng)于SQL中的select * from name where group by having order by limit m,n 這種順序一樣
$in
- 表示一個數(shù)據(jù)在多個數(shù)據(jù)中,類似于SQL中的
in
-
db.user.find({age:{$in:[22,33,44]}}) : 查找age in (22,33,44)之中的任意一個
$nin
- 相當(dāng)于SQL中的
not in
db.user.find({age:{$nin:[22,33,44]}})
$exists
- 表示不存在
-
db.user.find({sex:{$exists:false}}) : 查找不存在sex這個字段的文檔
slice
$slice操作符控制查詢返回的數(shù)組中元素的個數(shù)。此操作符根據(jù)參數(shù){ field: value } 指定鍵名和鍵值選擇出文檔集合,并且該文檔集合中指定array鍵將返回從指定數(shù)量的元素。如果count的值大于數(shù)組中元素的數(shù)量,該查詢返回數(shù)組中的所有元素的。
語法:db.collection.find( { field: value }, { array: {$slice: count }});
- 下面將查詢grades中的前兩個數(shù)
db.user.find({name:'jack'},{grades:{$slice:2},name:1,age:1,'school.name':1});
//輸出,可以看出這里的grades只輸出了前面兩個
{ "_id" : ObjectId("59057c16f551d8c9003d31df"), "name" : "jack", "age" : 22, "grades" : [ 22, 33 ], "school" : { "name" : "shida" } }
- 下面將輸出后3個數(shù)據(jù)
db.user.find({name:'jhon'},{grades:{$slice:-3},name:1});
//輸出
{ "_id" : ObjectId("59057c16f551d8c9003d31e0"), "name" : "jhon", "grades" : [ 22, 44, 88 ] }
- 下面介紹指定一個數(shù)組作為參數(shù)。數(shù)組參數(shù)使用[ skip , limit ] 格式,其中第一個值表示在數(shù)組中跳過的項目數(shù),第二個值表示返回的項目數(shù)。
db.user.find({name:'jack'},{grades:{$slice:[2,2]},name:1}); //這里將會跳過前面的兩個,直接得到后面的兩個數(shù)據(jù)
//輸出
{ "_id" : ObjectId("59057c16f551d8c9003d31df"), "name" : "jack", "grades" : [ 44, 55 ] }
count
- 統(tǒng)計數(shù)量
-
db.user.find().count() : 統(tǒng)計全部的數(shù)量
-
db.user.find({name:"Jack"}).count() : 統(tǒng)計name=Jack的人數(shù)
索引
-
db.collection.ensureIndex({key1:1}) : 創(chuàng)建索引,其中的key的值如果為1表示按照升序創(chuàng)建索引,-1表示降序創(chuàng)建索引
-
db.user.ensureIndex({name:1}) : 單個索引
-
db.user.ensureIndex({name:1,age:-1}) : 復(fù)合索引
ensureIndex() 接收可選參數(shù),可選參數(shù)列表如下:
db.user.find().pretty() : 這里沒有指定查詢條件,那么就是查詢?nèi)?/li>
projection來顯示指定的字段inclusion模式,指定返回的鍵,比如db.user.find({},{name:1}),這里只會顯示_id和name這兩個字段,其他的字段都是不會顯示的exclusion模式,指定不反回的鍵,比如db.user.find({},{name:0}) : 這里只會顯示age和_id,只有name不顯示db.user.find({},{name:1,age:0}) ,這個是不可以的db.user.find({name:"Jack"}) : 查詢name=Jack的全部文檔內(nèi)容db.user.find({name:"Jack"},{name:0}) : 不顯示name字段db.user.find({name:"Jack",age:22}) : 查詢name=Jack并且age=22的文檔信息db.user.find({$and:[{expression1},{expression2},{experssion3},......]})
-
db.user.find({$and:[{name:"Jack"},{age:22}]}): 和上面一樣的效果
db.user.find({$or:[{expression1},{expression2},{expression3}......]})
-
db.user.find({$or:[{name:"Jack"},{age:25}]}): 查找name=Jack或者age=25的文檔信息
db.user.find({name:"Jack",$or:[{_id:1},{age:22}]}) : 查找name=Jack and (_id=1 or age=22)
(>) 大于 - $gt(<) 小于 - $lt(>=) 大于等于 - $gte(<= ) 小于等于 - $lte(!=) 不等于 - $nedb.user.find({age:{$gt:22}}) : 查找 age>22的信息db.user.find({age:{$gte:22},name:"Jack"}) : 查找age>=22 and name=Jack的信息db.user.find().limit(2) : 只顯示兩條記錄db.user.find({name:"Jack"}).limit(2)db.user.find().skip(10) : 跳過前面的十條記錄,顯示后面的select * from user limit 20,5
db.user.find().skip(20).limit(5)
sort()方法對數(shù)據(jù)進行排序,sort()方法可以通過參數(shù)指定排序的字段,并使用 1 和 -1 來指定排序的方式,其中1 為升序排列,而-1是用于降序排列。db.collection.find().sort({key:1})db.user.find().sort({age:-1}) : 按照age降序排列db.user.find({},{name:1,age:1}).sort({age:-1,name:1}) : 按照name升序,age降序排列sort() --- > skip() ----> limit() ,這個相當(dāng)于SQL中的select * from name where group by having order by limit m,n 這種順序一樣in
db.user.find({age:{$in:[22,33,44]}}) : 查找age in (22,33,44)之中的任意一個
not in
db.user.find({age:{$nin:[22,33,44]}})db.user.find({sex:{$exists:false}}) : 查找不存在sex這個字段的文檔$slice操作符控制查詢返回的數(shù)組中元素的個數(shù)。此操作符根據(jù)參數(shù){ field: value } 指定鍵名和鍵值選擇出文檔集合,并且該文檔集合中指定array鍵將返回從指定數(shù)量的元素。如果count的值大于數(shù)組中元素的數(shù)量,該查詢返回數(shù)組中的所有元素的。
語法:db.collection.find( { field: value }, { array: {$slice: count }});
- 下面將查詢grades中的前兩個數(shù)
db.user.find({name:'jack'},{grades:{$slice:2},name:1,age:1,'school.name':1});
//輸出,可以看出這里的grades只輸出了前面兩個
{ "_id" : ObjectId("59057c16f551d8c9003d31df"), "name" : "jack", "age" : 22, "grades" : [ 22, 33 ], "school" : { "name" : "shida" } }
- 下面將輸出后3個數(shù)據(jù)
db.user.find({name:'jhon'},{grades:{$slice:-3},name:1});
//輸出
{ "_id" : ObjectId("59057c16f551d8c9003d31e0"), "name" : "jhon", "grades" : [ 22, 44, 88 ] }
- 下面介紹指定一個數(shù)組作為參數(shù)。數(shù)組參數(shù)使用[ skip , limit ] 格式,其中第一個值表示在數(shù)組中跳過的項目數(shù),第二個值表示返回的項目數(shù)。
db.user.find({name:'jack'},{grades:{$slice:[2,2]},name:1}); //這里將會跳過前面的兩個,直接得到后面的兩個數(shù)據(jù)
//輸出
{ "_id" : ObjectId("59057c16f551d8c9003d31df"), "name" : "jack", "grades" : [ 44, 55 ] }
db.user.find().count() : 統(tǒng)計全部的數(shù)量db.user.find({name:"Jack"}).count() : 統(tǒng)計name=Jack的人數(shù)db.collection.ensureIndex({key1:1}) : 創(chuàng)建索引,其中的key的值如果為1表示按照升序創(chuàng)建索引,-1表示降序創(chuàng)建索引
-
db.user.ensureIndex({name:1}): 單個索引 -
db.user.ensureIndex({name:1,age:-1}): 復(fù)合索引
ensureIndex() 接收可選參數(shù),可選參數(shù)列表如下:
| Parameter | Type | Description |
|---|---|---|
| background | Boolean | 建索引過程會阻塞其它數(shù)據(jù)庫操作,background可指定以后臺方式創(chuàng)建索引,即增加 "background" 可選參數(shù)。 "background" 默認值為false。 |
| unique | Boolean | 建立的索引是否唯一。指定為true創(chuàng)建唯一索引。默認值為false. |
| name | string | 索引的名稱。如果未指定,MongoDB的通過連接索引的字段名和排序順序生成一個索引名稱。 |
| dropDups | Boolean | 在建立唯一索引時是否刪除重復(fù)記錄,指定 true 創(chuàng)建唯一索引。默認值為 false. |
| sparse | Boolean | 對文檔中不存在的字段數(shù)據(jù)不啟用索引;這個參數(shù)需要特別注意,如果設(shè)置為true的話,在索引字段中不會查詢出不包含對應(yīng)字段的文檔.。默認值為 false. |
| expireAfterSeconds | integer | 指定一個以秒為單位的數(shù)值,完成 TTL設(shè)定,設(shè)定集合的生存時間。 |
| v | index version | 索引的版本號。默認的索引版本取決于mongod創(chuàng)建索引時運行的版本。 |
| weights | document | 索引權(quán)重值,數(shù)值在 1 到 99,999 之間,表示該索引相對于其他索引字段的得分權(quán)重。 |
| default_language | string | 對于文本索引,該參數(shù)決定了停用詞及詞干和詞器的規(guī)則的列表。 默認為英語 |
| language_override | string | 對于文本索引,該參數(shù)指定了包含在文檔中的字段名,語言覆蓋默認的language,默認值為 language. |
-
db.user.ensureIndex({age:1},{background:true}): 在后臺創(chuàng)建索引
聚合
-
db.collection.aggregate(pipeline,options)-
db.user.aggregate([{$group:{_id:null,count:{$sum:1}}}]): 查詢總數(shù),相當(dāng)于select count(*) from user,這里的聚合函數(shù)$sum表示求和,可以使用$引用集合中的字段,也可以直接使用數(shù)字,這里填寫1就表示查詢到一條記錄就加一,那么最后顯示的就是總數(shù)了。_id: 表示需要分組的字段,如果為null表示不分組
-
db.user.aggregate([{$group:{_id:"$name",sum_age:{$sum:"$age"}}}]): 根據(jù)字段name分組,對字段age求和,輸入如下
{ "_id" : "Mary", "sum_age" : 75 } { "_id" : "Jack", "sum_age" : 66 } { "_id" : "zhengyunamei", "sum_age" : 0 } { "_id" : "Tom", "sum_age" : 120 } { "_id" : "陳加兵", "sum_age" : 22 } { "_id" : "Lucy", "sum_age" : 66 } { "_id" : "鄭元梅", "sum_age" : 22 } -
-
db.user.aggregate([{$group:{_id:null,max_age:{$max:"$age"}}}]): 求出年齡最大的人信息
{ "_id" : null, "max_age" : 40 }
常用的聚合
| 表達式 | 描述 | 實例 |
|---|---|---|
| $sum | 計算總和。 | db.mycol.aggregate([{ |
| $avg | 計算平均值 | db.mycol.aggregate([{ |
| $min | 獲取集合中所有文檔對應(yīng)值得最小值。 | db.mycol.aggregate([{ |
| $max | 獲取集合中所有文檔對應(yīng)值得最大值。 | db.mycol.aggregate([{ |
| $push | 在結(jié)果文檔中插入值到一個數(shù)組中。 | db.mycol.aggregate([{ |
| $addToSet | 在結(jié)果文檔中插入值到一個數(shù)組中,但不創(chuàng)建副本。 | db.mycol.aggregate([{ |
| $first | 根據(jù)資源文檔的排序獲取第一個文檔數(shù)據(jù)。 | db.mycol.aggregate([{ |
| $last | 根據(jù)資源文檔的排序獲取最后一個文檔數(shù)據(jù) | db.mycol.aggregate([{ |
管道
管道在Unix和Linux中一般用于將當(dāng)前命令的輸出結(jié)果作為下一個命令的參數(shù)。
MongoDB的聚合管道將MongoDB文檔在一個管道處理完畢后將結(jié)果傳遞給下一個管道處理。管道操作是可以重復(fù)的。
表達式:處理輸入文檔并輸出。表達式是無狀態(tài)的,只能用于計算當(dāng)前聚合管道的文檔,不能處理其它的文檔。
這里我們介紹一下聚合框架中常用的幾個操作:
-
$project:修改輸入文檔的結(jié)構(gòu)??梢杂脕碇孛?、增加或刪除域,也可以用于創(chuàng)建計算結(jié)果以及嵌套文檔。 -
$match:用于過濾數(shù)據(jù),只輸出符合條件的文檔。$match使用MongoDB的標準查詢操作。 -
$limit:用來限制MongoDB聚合管道返回的文檔數(shù)。 -
$skip:在聚合管道中跳過指定數(shù)量的文檔,并返回余下的文檔。 -
$unwind:將文檔中的某一個數(shù)組類型字段拆分成多條,每條包含數(shù)組中的一個值。 -
$group:將集合中的文檔分組,可用于統(tǒng)計結(jié)果。 -
$sort:將輸入文檔排序后輸出。 -
$geoNear:輸出接近某一地理位置的有序文檔。
$math
- 這個相當(dāng)于where語句,用來過濾文檔的
- **這個位置是非常重要的,如果在
$group之前就是where子句,如果在之后,那么相當(dāng)于having子句** -
db.user.aggregate([{$match:{name:"Jack"}},{$group:{_id:null,count:{$sum:1}}}]): 統(tǒng)計name=Jack的人數(shù)- 這個命令相當(dāng)于SQL中的
select count(*) from user where name="Jack" - 我們可以使用
db.user.find({name:"Jack"}).count()同樣可以查詢、
- 這個命令相當(dāng)于SQL中的
-
db.user.aggregate([{$match:{age:{$gt:20}}},{$group:{_id:"$name",sum_age:{$sum:"$age"}}}])- 相當(dāng)于SQL中的
select _id,sum(age) as sum_age from user where age>20 group by name
- 相當(dāng)于SQL中的
-
db.user.aggregate([{$group:{_id:"$name",sum_age:{$sum:"$age"}}},{$match:{sum_age:{$gte:75}}}])select _id,sum(age) as sum_age from user group by name having sum_age>=75
-
db.user.aggregate([{$match:{name:"Tom"}},{$group:{_id:"$name",sum_age:{$sum:"$age"}}},{$match:{sum_age:{$gte:75}}}])select _id,sum(age) as sum_age from user where name="Tom" group by name having sum_age>=75
$limit
- 控制顯示的條數(shù),因為使用聚合之后,不能再使用
limit()方法來限制 -
db.user.aggregate([{$group:{_id:"$name",sum_age:{$sum:"$age"}}},{$limit:1}]): 根據(jù)姓名分組之后顯示一條數(shù)據(jù)- 相當(dāng)于
select _id,sum(age) as sum_age from user group by name limit 0,1
- 相當(dāng)于
-
db.user.aggregate([{$match:{name:"Tom"}},{$group:{_id:"$name",sum_age:{$sum:"$age"}}},{$match:{sum_age:{$gte:75}}},{$skip:0},{$limit:1}])select _id ,sum(age) as sum_age from user where name="Tom" group by name having age>=75 limit 0,1
$sort
- 排序輸出
db.collection.aggregate([{},{},{},......,{$sort:{key:1}}])-
db.user.aggregate([{$match:{name:"Tom"}},{$group:{_id:"$name",sum_age:{sum:"age"}}},{$match:{sum_age:{$gte:75}}},{$sort:{sum_age:1}},{$skip:0},{$limit:1}])select _id ,sum(age) as sum_age from user where name="Tom" group by name having age>=75 order by sum_age asc limit 0,1
總結(jié)
- 常用的格式:
db.collection.aggregate([{$match:{key:value,...},{$group:{_id:value,..}},{$match:{key:value,....}},{$sort:{key:1,key2:-1}},{$skip:num},{$limit:num}])- 對應(yīng)SQL中的語句為:
select _id,key1,key2 from collection where group by order by limit n,m
- 對應(yīng)SQL中的語句為: