一.MongoDB中的Count函數、Distinct函數以及分組
?準備工作,插入一個班級的文檔
> for(var i=0;i<10;i++){
... db.Classes.insert({ClassName:"Class"+i,_id:i});
... }
WriteResult({ "nInserted" : 1 })
> db.Classes.find()
{ "_id" : 0, "ClassName" : "Class0" }
{ "_id" : 1, "ClassName" : "Class1" }
{ "_id" : 2, "ClassName" : "Class2" }
{ "_id" : 3, "ClassName" : "Class3" }
{ "_id" : 4, "ClassName" : "Class4" }
{ "_id" : 5, "ClassName" : "Class5" }
{ "_id" : 6, "ClassName" : "Class6" }
{ "_id" : 7, "ClassName" : "Class7" }
{ "_id" : 8, "ClassName" : "Class8" }
{ "_id" : 9, "ClassName" : "Class9" }
>
?
1.count函數
如上面,如果要統計班級的數目,可以使用count函數進行統計
> db.Classes.find().count()
10
>
?
2.Distinct函數
修改一下Classes文檔,添加一條重復的數據
> db.Classes.insert({_id:10,ClassName:"Class9"})
WriteResult({ "nInserted" : 1 })
> db.Classes.find()
{ "_id" : 0, "ClassName" : "Class0" }
{ "_id" : 1, "ClassName" : "Class1" }
{ "_id" : 2, "ClassName" : "Class2" }
{ "_id" : 3, "ClassName" : "Class3" }
{ "_id" : 4, "ClassName" : "Class4" }
{ "_id" : 5, "ClassName" : "Class5" }
{ "_id" : 6, "ClassName" : "Class6" }
{ "_id" : 7, "ClassName" : "Class7" }
{ "_id" : 8, "ClassName" : "Class8" }
{ "_id" : 9, "ClassName" : "Class9" }
{ "_id" : 10, "ClassName" : "Class9" }
?
現在我想查詢所有ClassName,去掉重復的,可以執行下面的操作。
> db.runCommand({distinct:"Classes",key:"ClassName"}).values
[
??????? "Class0",
??????? "Class1",
??????? "Class2",
??????? "Class3",
??????? "Class4",
??????? "Class5",
??????? "Class6",
??????? "Class7",
??????? "Class8",
??????? "Class9"
]
>
去重語法 db.runCommand({distinct:"數據集合名字",key:"需要去重的鍵"}).values
?
3.Group分組操作(比較復雜)
語法:
db.runCommand({group:{
?????? ?ns:集合名字,
?Key:分組的鍵對象,
?Initial:初始化累加器,
?$reduce:組分解器,
?Condition:條件,
?Finalize:組完成器
????? }})
?
?1).key:用來分組文檔的字段。和keyf兩者必須有一個
?2).keyf:可以接受一個javascript函數。用來動態的確定分組文檔的字段。和key兩者必須有一個
?3).initial:reduce中使用變量的初始化
?4).reduce:執行的reduce函數。函數需要返回值。
?5).cond:執行過濾的條件。
?6).finallize:在reduce執行完成,結果集返回之前對結果集最終執行的函數。可選的。
?
具體的使用可以參考手冊:http://mongodb-documentation.readthedocs.org/en/latest/reference/command/group.html
分組首先會按照key進行分組,每組的 每一個文檔全要執行$reduce的方法,他接收2個參數一個是組內本條記錄,一個是累加器數據.
?
新建一個persons集合,插入一下數據
var persons = [{
name:"Tom",
age:25,
country:"USA"
},
{
name:"Jack",
age:25,
country:"USA"
},
{
name:"Lucy",
age:26,
country:"USA"
},
{
name:"DaChengzi",
age:27,
country:"China"
},
{
name:"Xiaojuz",
age:26,
country:"China"
},
{
name:"DaPingguo",
age:27,
country:"China"
},
{
name:"XiaoBoluo",
age:27,
country:"China"
},
{
name:"Bangzi1",
age:26,
country:"Korea"
},
{
name:"LiShishi",
age:27,
country:"Korea"
},
{
name:"Rain",
age:21,
country:"Korea"
},
{
name:"CangJingkong",
age:30,
country:"Japan"
}]
for(var i = 0;i<persons.length;i++){
db.persons.insert(persons[i])
}
插入完成后,查看一下:
?
現在我有一個需求,想要找到每個國家當中年紀最大的人,并且年紀不大于30歲,輸出他們的名字
?
思路: ①先按照國家進行分組
? ? ? ? ?②找到每個國家中年紀最小的
? ? ? ? ?③判斷年紀是不是小于30
?
編寫查詢:
db.runCommand({group:{
ns:"persons",
key:{"country":true},
initial:{age:0},
$reduce:function(doc,prev){
if(doc.age>prev.age){
prev.age=doc.age;
prev.name = doc.name;
prev.country = doc.country;
}
},
condition:{age:{$lt:30}}
}})
?
運行結果:
{
??????? "retval" : [
???????? {
????????????? "country" : "USA",
????????????? ?"age" : 26,
??????????????????????? "name" : "Lucy"
??????????????? },
??????????????? {
??????????????????????? "country" : "China",
??????????????????????? "age" : 27,
??????????????????????? "name" : "DaChengzi"
??????????????? },
??????????????? {
??????????????????????? "country" : "Korea",
??????????????????????? "age" : 27,
??????????????????????? "name" : "LiShishi"
??????????????? }
??????? ],
??????? "count" : 10,
??????? "keys" : 3,
??????? "ok" : 1
}
?
從結果看到日本女士蒼井空的年齡是30,被我篩選掉了…...
?
Finallize的使用,如果覺得返回的東西太過單調,可以使用finalize進行再次的修改
?
例如:
db.runCommand({group:{
ns:"persons",
key:{"country":true},
initial:{age:0},
$reduce:function(doc,prev){
if(doc.age>prev.age){
prev.age=doc.age;
prev.name = doc.name;
prev.country = doc.country;
}
},
finalize:function(prev){
prev.age = "Age is" +prev.age;
prev.name = "Name is " + prev.name;
prev.country = "Country is " + prev.country;
},
condition:{age:{$lt:30}}
}})
?
加上上面之后,查詢的結果如下:
{
??????? "retval" : [
??????????????? {
??????????????????????? "country" : "Country is USA",
??????????????????????? "age" : "Age is26",
??????????????????????? "name" : "Name is Lucy"
??????????????? },
??????????????? {
??????????????????????? "country" : "Country is China",
??????????????????????? "age" : "Age is27",
??????????????????????? "name" : "Name is DaChengzi"
??????????????? },
??????????????? {
??????????????????????? "country" : "Country is Korea",
??????????????????????? "age" : "Age is27",
??????????????????????? "name" : "Name is LiShishi"
??????????????? }
??????? ],
??????? "count" : 10,
??????? "keys" : 3,
??????? "ok" : 1
}
可以看到每一項數據前面,都加上了說明文字,所以說finialize是可以對分完組之后的數據在做一次修改的。
?
二.命令執行器(db.runCommand())
1.之前我們遇到刪除集合,一般使用的方法是 db.集合名.drop()
使用命令執行器:
db.runCommand({drop:"集合"})
?
2.查找MongoDB為我們提供的命令
①在shell中執行:db.listCommands()
②訪問網址http://127.0.0.1:28017/_commands
?
3.常用命令
略
三.固定集合(Capped Collection)
1.解釋:就是固定size的集合唄。
2.特點:性能出色的有著固定大小的集合,以LRU(Least Recently Used最近最少使用)規則和插入順序進行age-out(老化移出)處理,自動維護集合中對象的插入順序,在創建時需要預先指定大小。如果空間用完,新添加的對象將會取代集合中最舊的對象永遠保持最新的數據
總結就是以下:
①固定集合默認是沒有索引的就算是_id也是沒有索引的
②由于不需分配新的空間他的插入速度是非常快的
③固定集合的順是確定的導致查詢速度是非常快的
④最適合的是應用就是日志管理
3.使用
①創建一個固定集合
? 創建一個新的固定集合要求大小是100個字節,可以存儲文檔10個
?> db.createCollection("myCapped",{size:100,capped:true,max:10})
??? { "ok" : 1 }
?>
?
②把一個普通集合轉成固定集合
> db.runCommand({convertToCapped:"Classes",size:100000})
{ "ok" : 1 }
>
?
③插入數據
文檔最大為10個,那么當插入11條數據的時候,會出現什么情況呢,根據之前的概念,應該是吧第一條數據踢出去,然后加入最后一條
> for(var i = 0; i<11;i++){
... db.myCapped.insert({name:"name"+i,_id:i})
... }
WriteResult({ "nInserted" : 1 })
> db.myCapped.find()
{ "_id" : 1, "name" : "name1" }
{ "_id" : 2, "name" : "name2" }
{ "_id" : 3, "name" : "name3" }
{ "_id" : 4, "name" : "name4" }
{ "_id" : 5, "name" : "name5" }
{ "_id" : 6, "name" : "name6" }
{ "_id" : 7, "name" : "name7" }
{ "_id" : 8, "name" : "name8" }
{ "_id" : 9, "name" : "name9" }
{ "_id" : 10, "name" : "name10" }
>
> db.myCapped.insert({name:"name11",_id:11})
WriteResult({ "nInserted" : 1 })
> db.myCapped.find()
{ "_id" : 2, "name" : "name2" }
{ "_id" : 3, "name" : "name3" }
{ "_id" : 4, "name" : "name4" }
{ "_id" : 5, "name" : "name5" }
{ "_id" : 6, "name" : "name6" }
{ "_id" : 7, "name" : "name7" }
{ "_id" : 8, "name" : "name8" }
{ "_id" : 9, "name" : "name9" }
{ "_id" : 10, "name" : "name10" }
{ "_id" : 11, "name" : "name11" }
>
④刪除數據
> db.myCapped.remove({_id:11})
WriteResult({
??????? "nRemoved" : 0,
??????? "writeError" : {
??????????????? "code" : 10101,
??????????????? "errmsg" : "cannot remove from a capped collection: mongoDBTest.myCapped"
??????? }
})
>
如上例,固定集合是不能進行數據刪除的。
綜上:固定集合有點像一個隊列,先進先出,大小不變。
?
?
?
?
?
?
?
?