1、count
————————————————————————
> db.ysq.count()
// 执行速度很快
> db.ysq.count({"x" : 1}) // 增加查询条件会使count变慢
> db.ysq.count({"x" : 1}) // 增加查询条件会使count变慢
2、distinct
————————————————————————
> db.runCommand( {
"distinct" :
"people", "key"
: "age" } )
3、group
与关系型数据库的 GROUP BY 差不多。
例子:在最近30天的股价集合中获取每天收市价
————————————————————————
-- 股价文档:
{ "day" : "2013/06/07" , "time" : "2013/06/07 23:22:53 GMT-400" ,"price" : "4.23" }
-- group
> db.runCommand( { "group" :
"ns" : "ysq" , -- 指定要进行分组的集合
"key" : "day" , -- 指定文档分组依据的键
"inital" : { "time" : 0 } ,-- 每一组reduce函数调用的初始时间
"$ruduce" : function(doc, prev) { -- 每个文档都对应一次调用,doc为当前文档,prev为本组当前结果
if (doc.time > prev.time) {
prev.price = doc.price ;
prev.time = doc.time ;
}
} ,
"condition" : { "day" : { "$gt" : "2013/05/07" } } -- 过滤条件,condition也可简写为cond或q
} )
-- 结果
{
"retval" : -- 返回的文档数组
[
{
"day" : "2013/06/07" , -- 默认加进来的
"time" : "2013/06/07 23:22:53 GMT-400" , -- 初始化设置,然后主动更新
"price" : "4.23" -- price是显式设置的
} ,
... ...
],
"count" : 734, --使用的文档总是
"keys" : 30,-- key有多少个不同的值
"ok" : 1
}
{ "day" : "2013/06/07" , "time" : "2013/06/07 23:22:53 GMT-400" ,"price" : "4.23" }
-- group
> db.runCommand( { "group" :
"ns" : "ysq" , -- 指定要进行分组的集合
"key" : "day" , -- 指定文档分组依据的键
"inital" : { "time" : 0 } ,-- 每一组reduce函数调用的初始时间
"$ruduce" : function(doc, prev) { -- 每个文档都对应一次调用,doc为当前文档,prev为本组当前结果
if (doc.time > prev.time) {
prev.price = doc.price ;
prev.time = doc.time ;
}
} ,
"condition" : { "day" : { "$gt" : "2013/05/07" } } -- 过滤条件,condition也可简写为cond或q
} )
-- 结果
{
"retval" : -- 返回的文档数组
[
{
"day" : "2013/06/07" , -- 默认加进来的
"time" : "2013/06/07 23:22:53 GMT-400" , -- 初始化设置,然后主动更新
"price" : "4.23" -- price是显式设置的
} ,
... ...
],
"count" : 734, --使用的文档总是
"keys" : 30,-- key有多少个不同的值
"ok" : 1
}
注:有的文档没有包含依据的键,会被分到一组,以"day" : null 形式存在。在"condition"中加入"day" : {"$exits" : true}可过滤该组
3.1、使用完成器
例子:每篇博客文章有多个标签tag。现要找出每天最热点的标签。
————————————————————————
-- 先按天分组,为每个标签计数:
db.posts.group({
"key" : {"tags" : true},
"initial" : {"tags" : {}},
"$reduce" : function(doc, prev) {
for(i in doc.tags) {
if(doc.tags[i] in prev.tags) {
prev.tags[doc.tags[i]] ++ ;
} else {
prev.tags[dov.tags[i]] = 1;
}
}
}
})
-- 结果:
[
{"day" : "2012/01/12","tags" : {"nosql" : 4,"winter" : 10,"sledding" : 2} },
{"day" : "2012/01/13","tags" : {"soda" : 5,"php" : 2} },
{"day" : "2012/01/14","tags" : {"python" : 6,"winter" : 4,"nosql" : 15} }
]
-- 使用完成器精减结果
"finalize" : function(prev) {
var mostPopular = 0 ;
for ( i in prev.tags ) {
if( prev.tags[i] > mostPopular ) {
prev.tag = i;
mostPopular = prev.tags[i];
}
}
delete prev.tags;
}
-- 结果:
[
{"day" : "2012/01/12","tags" : "winter"},
{"day" : "2012/01/13","tags" : "soda" },
{"day" : "2012/01/14","tags" : "nosql"} }
]
db.posts.group({
"key" : {"tags" : true},
"initial" : {"tags" : {}},
"$reduce" : function(doc, prev) {
for(i in doc.tags) {
if(doc.tags[i] in prev.tags) {
prev.tags[doc.tags[i]] ++ ;
} else {
prev.tags[dov.tags[i]] = 1;
}
}
}
})
-- 结果:
[
{"day" : "2012/01/12","tags" : {"nosql" : 4,"winter" : 10,"sledding" : 2} },
{"day" : "2012/01/13","tags" : {"soda" : 5,"php" : 2} },
{"day" : "2012/01/14","tags" : {"python" : 6,"winter" : 4,"nosql" : 15} }
]
-- 使用完成器精减结果
"finalize" : function(prev) {
var mostPopular = 0 ;
for ( i in prev.tags ) {
if( prev.tags[i] > mostPopular ) {
prev.tag = i;
mostPopular = prev.tags[i];
}
}
delete prev.tags;
}
-- 结果:
[
{"day" : "2012/01/12","tags" : "winter"},
{"day" : "2012/01/13","tags" : "soda" },
{"day" : "2012/01/14","tags" : "nosql"} }
]
3.2 将函数作为键使用
例子:由于每个作者习惯不一样,刚才的tag,可能有些作者写的是"nosql",有些写的是"noSql",这时可以使用函数作为键
定义分组函数就要用到$keyf(不再是key)
————————————————————————
"$keyf" : function(x) {return x.category.toLowerCase();}
4、MapReduce
(略)