`
forever1121
  • 浏览: 16535 次
  • 性别: Icon_minigender_2
  • 来自: 齐齐哈尔
社区版块
存档分类
最新评论

MongoDB权威指南_学习笔记2

阅读更多
用$where可以执行任意的js作为查询的一部分。
db.foo.find({"$where" : function(){
         for(var current in this){
            for(var other in this){
               if(current != other && this[current] == this[other]){
                  return true;
               }    
            }
         }
      }
      return false;
})

db.foo.find({"$where" : "this.x + this.y ==10"})
等价于 db.foo.find({"$where" : "function(){return this.x + this.y == 10;}"})

$where的查询速度比常规查询速度慢很多,每个文档都要从从BSON转换成js对象,然后通过$where的表达式来运行。同样不能利用索引。

数据库使用游标来返回find的执行结果。客户端对游标的实现通常能够对最终结果进行有效的控制。若要在shell中创建一个游标,首先要对集合填充一些文档,然后对其执行查询,并将结果分配给一个局部变量。

for(i=0 ; i<100 ; i++){
    db.c.insert({x : i});
}
var cursor = db.collection.find();

while(cursor.hasNext()){     //hasNext()检查是否有后续结果存在
      obj = cursor.next();   //next()获取它的值
}

var cursor = db.people.find();
cursor.forEach(function(x){
    print(x.name);
})

最常用的查询选项就是限制返回结果的数量,忽略一定数量的结果并排序。所有这些选项一定要在被派发到服务器之前添加。(limit skip sort)
db.c.find().limit(3)  //限制结果数量
db.b.find().skip(3)   //略过前3个文档
sort用一个对象作为参数:一组键/值对,键对应文档的键名,值代表排序的方向。排序方向可以是升序(1)或降序(-1)。若指定了多个键,则按照多个键的顺序逐个排序。
db.stock.find({"deav" : "mp3"}).limit(50).sort({"price" : -1})

MongoDB处理不同类型的数据是有一个顺序的。有时候一个键值往往是多种类型的。其排序顺序是预先定义好的。从小到大的顺序是:最小值、null、数字(整型、长整型、双精度)、字符串、对象/文档、数组、二进制数据、对象ID、布尔型、日期型、时间戳、正则表达式、最大值。

避免使用skip略过大量结果,这样skip会变得很慢。通常可以向文档本身内置查询条件,来避免过的的skip。
分页(不使用skip):
var page1 = db.foo.find().sort({"date" : -1}).limit(100);
var latest = null;
while(page1.hasNext()){
    latest = page1.next();
    display(latest);
}
var page2 = db.foo.find({"date" : {"$get" : latest.date}});
page2.sort({"date" : -1}).limit(100);

查询分为包装的和普通的两类。绝大多数驱动程序有些辅助措施向查询添加各种选项:
$maxsan : integer    制定查询最多扫描的文档数量
$min : document      查询的开始条件
$max : max           查询的结束条件
$hint : document     指定服务器使用哪个索引进行查询
$explain : boolean   获取查询执行的细节,而并非真正执行查询
$snapshot : boolean  确保查询的结果是在查询执行那一刻的一致快照

在服务器端,游标消耗内存和其他资源。游标遍历尽了结果以后,或者客户端发来消息要求终止,数据库将会释放这些资源。释放的资源可以被数据库换做他用,所以要尽量保证尽快释放游标。还有一些情况在作用域内了,驱动会向服务器发送专门的消息,让其销毁游标。最后,即便用户也没有迭代完所有结果,并且游标也还在作用域中,10分钟不用,数据库游标也会自动销毁。

创建索引要使用ensureIndex()方法
db.people.ensureIndex({"username" : 1})
MongoDB的查询优化器会重排查询项的顺序,以便利用索引。
创建索引的缺点就是每次插入、更新和删除时都会产生额外的开销。这是因为数据库不但需要执行这些操做,还要将这些操作在索引中标记。因此,要尽可能少创建索引。每个集合默认的最大索引个数为64个。要是查询返回一半以上的结果,用表扫描会比索引高效一些。

集合中的每个索引都有一字符串类型的名字,来唯一标识索引。服务器通过这个名字来删除或者操作索引。索引名有字符个数的限制,所以特别复杂的索引在创建时一定要使用自定义的名字。
db.foo.ensureIndex({"a" : 1, "b" : 1, "c" : 1,..., "z" : 1},{"name" : "alphabet"})

唯一索引可以确保集合的每一个文档的指定键都有唯一值。
db.people.ensureIndex({"username" : 1},{"unique" : true})

当为已有的集合创建索引,这是会造成数据重复,dropDups选项可以保留发现的第一个文档,而删除接下来的有重复值的文档。
db.people.ensureIndex({"username" : 1},{"unique" : true, "dropDups" : true})

创建复合唯一索引的时候,单个键的值可以相同,只要组合起来的值不同即可。

explain会帮助你获得查询方面诸多有用的信息。只要对游标调用该方法,就可以得到查询细节。explain会返回一个文档,而不是游标本身。explain会返回查询使用的索引情况,耗时及扫描文档数的统计信息。
db.foo.find().explain()
//output
{
   "cursor" : "BasicCursor",  //没有使用索引
   "indexBounds" : [ ],    
   "nscanned" : 64,           //数据库查找了多少个文档
   "nscannedObjects" : 64,
   "n" : 64,                  //返回文档的数量
   "millis" : 0,              //数据库执行查询的时间
   "allPlans" : [
      {
           "cursor" : "BasicCurosr",
           "indexBounds" : [ ]
      }
   ]
}

//假设查询一个基于"age"键的索引。
db.c.find({age : {$gt : 20, $lt : 30 }}).explain()
//output
{
    "cursor" : "BtreeCursor age_1"
    "indexBounds" :[
        [
            {
               "age" : 20
            },
            {
                "age" : 30
            }
        ]
    ],
    "nscanned" : 14,
    "nscannedObjects" : 12,
    "n" : 12,
    "millis" : 1,
    "allPlans" : [
        {
           "cursor" : "BtreeCursor age_1",
           "indexBounds" : [ 
               [
                   {
                       "age" : 20
                   },
                   { 
                       "age" : 30
                   }
               ]
           ]
        }
    ]
}

可以使用hint强制使用某个索引。
db.c.find({"age" : 14, "username" : /.*/}).hint({"username" : 1, "age" : 1})
多数情况下,MongoDB的查询优化器非常智能,会替你选择该用那个索引。初次做某个查询时,查询优化器会同时尝试各种查询方案。最先完成的被确定使用,其他的则终止掉。查询方案被记录下来,以备日后对应相同键的查询。查询优化器定期充实其他方案,以防因添加新的数据后,之前的方案不再是最优。

索引的元信息存储在每个数据库的system.indexes集合中。这是一个包保留集合。不能对其插入或者删除文档。只能通过ensureIndex或DropIndexes进行。system.indexes集合包含每个索引的详细信息,同时system.namespaces集合也含有索引的名字。

db.people.ensureIndex({"username" : 1},{"background" : true})
建立索引既耗时又费力,还需消耗很多资源。使用{"background" : true}后,可以使这个过程在后台完成,同时正常处理请求。要是不包括{"background" : true},数据库会阻塞建立索引期间的所有请求。

db.runCommand({"dropIndexes" : "foo", "index" : "*"})//删除所有索引

地理空间索引:找到离当前位置最近的N个场所。MongoDB为坐标平面查询提供了专门的索引。
db.map.ensureIndex({"gps" : "2d"})gps的键值必须是某种形式的一对值:一个包含两个元素的数组或包含两个键的内嵌文档。
默认的情况下,地理空间索引假设值的范围是-180~180。要想用其他值,可以通过ensureIndex的选项指定最大最小值。
db.star.trek.ensureIndex({"light-years" : "2d"},{"min" : -1000, "max" : 1000})

地理空间查询以两种方式进行,即普通查询(find)或使用数据库命令。
db.map.find({"gps" : [40, -73] })  //默认返回100个文档
db.runCommand({goNear : "map", near : [40, -70], num : 10})
goNear还会返回每个文档到查询点的距离。

MongoDB可以找到指定形状内的文档。
$box  矩形(第一个参数指定了左下角的坐标、第二个指上角的坐标)
db.map.find({"gaps" : {"$within" : {"$box" : [10, 20], [15, 30] }}})
$center  圆形内部所有的点(第一个参数指定圆心坐标、第二个参数指定半径)
db.map.find({"gps" : {"$within" : {"$center" : [12, 25], 5}}})

count:返回集合中的文档数量
db.foo.count()
db.foo.count({"c" : 1})

distinct:找出给定键的所有不同的值。使用时必须指定集合和键。
db.runCommand({"distinct" : "people", "key" : "age"})

group:先选定分组所依据的键,而后MongoDB就会将集合依据所选定键值的不同分成若干组,然后可以通过聚合每一组内的文档,产生一个结果文档。
[
   {"time" : "10/3/2010 05:00", "price" : 4.10},
   {"time" : "10/4/2010 04:00", "price" : 4.82},
   {"time" : "10/5/2010 11:00", "price" : 4.02}
]
db.runCommand({"group" : {
     "ns" : "stocks",      //指定要进行分组的集合
     "key" : "day",        //指定文档分组依据的键
     "initial" : {"time" : 0},    //每一组reduce函数调用的初始时间,会作为初始文档传递给后续过程
     "$reduce" : function(doc,prev){ //每个文档都对应一次这个调用。系统会传递两个参数:当前文档和累加器文档
        if(doc.time > prev.time){
           prev.price = doc.price;
           prev.time = doc.time;
        }
     },
      "conditon" : {"day" : {"$gt" : "2010/10/2"}}
   }
})

完成器(finalizer)用以精简从数据库传到用户的数据。
db.runCommand({"group" : {
     "ns" : "posts",
     "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[doc.tags[i]] = 1;
          }
       },
       "finalize" : function(prev){
          for(i in prev.tags){
              if(prev.tags[i] > mostPopular){
                   prev.tag = i ;
                   mostPopular = prev.tag[i];
              }
          }
       delete prev.tags
       }   
     }
   }
})

定义分组函数要用$keyf键。
db.posts.group({
     "ns" : "posts",
     "$keyf" : function(x) {return x.category.toLowerCase();},
     "initializer" : ...        
})

MapReduce是一个可以轻松并行化到多个服务器的聚合方法。它会拆分问题,再将各个部分发送到不同的机器上,让每台机器都完成一部分。当所有及其都完成的时候,再把结果汇集起来形成最终完整的结果。MapReduce需要几个步骤:最开始是映射,将操作映射到集合中的每个文档。然后就是中间环节,称为洗牌(shuffle),按照键分组,并将产生的键值组成列表放到对应的键中。化简(reduce)则把列表中的值化简成一个单值。这个值被返回,然后接着洗牌,直到每个键的列表只有一个值为止。

map = function(){
    for(var key in this){
         emit(key, {count : 1});
    }
};

reuduce = function(key,emits){
    total = 0;
    for(var i in emits){
        total =+ emits[i].count;
    }
    return {"count" : total};
}

mr = db.runCommand({"mapreduce" : "foo", "map" : map, "reduce" : reduce})
//output
{
    "result" : "tmp.mr.mapreduce_165_1", //存放mapReduce结果的集合名,是一个临时集合,MapReduce的连接关闭后自动被删除
    "timeMills" : 12,    //操作花费的时间
    "counts" : {   
       "input" : 6      //发送到map函数的文档个数
        "emit" : 14      //在map函数中emit被调用的次数
        "output" : 5     //结果集合中创建的文档数量
    }
    "ok" : true
}
db[mr.result].find()  //对结果集合进行查询

map = function(){
   for(var i in this.tag){
      var recency = 1/(new Date() - this.date);
      var score = recency * this.score;
   
      emit(this.tag[i], {"urls" : [this.url], "score" : score});
   }
};
reuduce = function(key, emits){
   var total = {urls : [], score : 0}
   for (var i in emits){
      emits[i].urls.forEach(function(url){
         total.urls.push(url);
      }
      total.score += emits[i].score;
   }
   return total;
};

MapReduce的其它可选键:
finalize:函数   将reduce的结果发送给这个值,这是处理过程的最后一步
keeptemp:布尔   连接关闭临时结果集合是否保存
output:字符串   结果集合的名字。设定该项则隐含着keeptemp : true
query:文档      会在发往map函数前,先用指定条件过滤文档
sort:文档       在发往map前先给文档排序
limit:整数      发往map函数的文档数量的上限
scope:文档      js代码中要用到的变量
verbose:布尔   是否产生更加详尽的服务器日志

获得MongoDB所有命令的最新列表有2种方式:在shell这运行db.listCommands();在浏览管理员接口http://localhost:28017/_commands
MongoDB常用命令:
buildInfo:管理员专用命令,返回MongoDB服务的版本号和主机的操作系统
{"buildInfo" : 1}
collStats:返回指定集合的统计信息,包括数据大小、已分配的存储空间和索引大小
{"collStats" : collection}
distinct:列出指定集合中满足查询条件的文档的指定键的所有不同值
{"distinct" : collection, "key" :key, "query" : query}
drop:删除集合所有数据
{"drop" : collection}
dropDatabase:删除当前数据库的所有数据
{"dropDatabase" : 1}
dropIndexes:删除集合里面名称为name的索引,若名称为*,则删除所有索引
{"dropIndexes" : collection, "index" : name }
getLastError:查看对本集合执行的最后一次操作的错误信息或其他状态信息,在n太服务器复制集合的最后操作之前,这个命令会堵塞
{"getLastError" : 1[, "w" : w[, "wtimeout" : timeout]]}
isMaster:检查本服务器是主服务器还是从服务器
{"isMaster" : 1}
ListCommands:返回所有可以在服务器上运行的命令及相关信息
{"listCommands" : 1}
listDatabase:管理专用命令,列出服务器上所有的数据库
{"listDatabase" : 1}
ping:检查服务器链接是否正常,即便服务器上锁,也会立刻返回
{"ping" : 1 }
renameCollection:将集合a重命名为b,其中a和b都必须是完整的集合命名空间。
{"renameCollection" : a, "to" : b}
repairDatabase:修复并压缩当前数据库,这个操作可能非常耗时
{"repairDatabase" : 1}
serverStatus:返回这台服务器的管理统计信息
{"serverStatus" : 1}

MongoDB支持固定集合,要事先创建并固定大小。当空间不足时,最早的文档就会被删除。在默认的情况下,固定集合没有索引。
创建固定集合:
db.createCollection("my_collection", {capped : true, size : 100000, max = 100});
通过转换已有的普通集合的方式来创建固定集合:
db.runCommand({convertToCapped : "test", size : 10000})
固定集合有种特殊的排序方式,叫做自然排序。自然排序就是文档在磁盘上的顺序。

尾部游标是一种特殊的持久游标,这类游标不会在没有结果后销毁。游标收到tail-f命令的启发,会尽可能持续地获取结果输出。因为这类游标在没有结果后不销毁,所以一旦有新文档添加到集合里面就会被取回并输出。尾部游标只能用在固定集合上。
分享到:
评论

相关推荐

    mongodb_java_2.6_API

    2. **连接MongoDB服务器** 使用`MongoClient`类建立到MongoDB服务器的连接。通过提供主机名和端口号,可以创建一个`MongoClient`实例,然后通过客户端访问不同的数据库。 ```java MongoClient mongoClient = new...

    MongoDB权威指南中文版.pdf

    由于提供的文件内容中存在大量重复内容,并且没有具体的章节段落,因此无法直接生成详细知识点。...如果需要对MongoDB有更全面的了解,推荐查找该权威指南的完整版电子书籍或其他专业资源进行学习。

    navicat121_mongodb_cs_x64+navicat121_mongodb_cs_x86.rar

    标题中的"navicat121_mongodb_cs_x64+navicat121_mongodb_cs_x86.rar"指示了这是一个包含两个版本的Navicat for MongoDB安装程序的压缩包,一个是针对64位操作系统(x64),另一个是针对32位操作系统(x86)。...

    navicat121_mongodb_en_x64.exe

    可视化工具mongodb操作简单,可视化强 欢迎大家下载

    navicat150_mongodb_cs_x64.exe

    navicat可以连接MongoDB数据库,也可以连接oracle和mysql等其他的数据库,挺好用的

    MongoDB权威指南 中文版高清PDF

    《MongoDB权威指南》是一本深入解析该技术的专业书籍,旨在帮助读者全面理解和掌握MongoDB的使用。 本书首先从数据库的基础概念入手,介绍了NoSQL数据库与传统关系型数据库的区别,阐述了MongoDB作为文档数据库的...

    MongoDB权威指南.pdf

    英文版:MongoDB: The Definitive Guide内容简介《MongoDB权威指南》是一本广受好评的MongoDB方面的图书。与传统的关系型数据库不同,MongoDB是一种面向文档的数据库。书中介绍了面向文档的存储方式及利用MongoDB的...

    MongoDB权威指南(中英文两版)

    "MongoDB权威指南"是学习和深入理解这一技术的重要参考资料,提供了全面的理论知识和实践经验。本书分为中文版和英文版,适合不同语言背景的读者,帮助他们掌握MongoDB的核心概念和操作技巧。 在中文版的《MongoDB...

    mongodb学习笔记和mongodb权威指南

    这份压缩包文件包含了关于MongoDB的全面学习资源,包括与Python集成的实践、权威指南、学习手册以及综合总结,旨在帮助用户深入理解和掌握这个数据库系统。 首先,`mongodb_and_python`学习笔记可能涵盖了如何使用...

    MongoDB_Architecture_Guide

    MongoDB架构指南包含了关于MongoDB数据库系统的内部架构设计、运作原理和管理实践的深入介绍。本文档的结构主要分为以下几个部分: 1. 引言(Introduction) 文档的引言部分概述了MongoDB的开发背景,强调了它不是...

    MongoDB 权威指南.pdf

    ### MongoDB权威指南知识点详解 #### 一、MongoDB概述 MongoDB是一款开源的NoSQL数据库系统,采用BSON(Binary JSON)格式存储文档数据。它支持动态查询、高可用性及横向扩展等特性,适用于大数据量的应用场景。...

    MongoDB权威指南 第二版中文 mobi

    MongoDB权威指南 第二版中文 mobi

    MongoDB权威指南中文版高清版带书签PDF

    在《MongoDB权威指南》这本书中,作者详细地介绍了MongoDB的基础知识、安装配置、数据模型、查询语言、操作管理以及高级特性。以下是对这本书中核心知识点的概述: 1. **MongoDB基础知识**:MongoDB是NoSQL数据库的...

    MongoDB权威指南中文版

    《MongoDB权威指南中文版》第1章 简介 第2章 入门 第3章 创建、更新及删除文档 第4章 查询 第5章 索引 第6章 聚合 第7章 进阶指南 第8章 管理 第9章 复制 第10章 分片 第11章 应用举例 附录A 安装MongoDB 附录B ...

Global site tag (gtag.js) - Google Analytics