MongoDB权威指南(6)- 高级主题

jopen 13年前
     <div style="line-height:20px;font-family:Verdana,Geneva,Arial,Helvetica,sans-serif;font-size:13px;" id="cnblogs_post_body">     <p style="margin:5px auto;"><strong>1.数据库命令</strong></p>     <p style="margin:5px auto;">mongoDB提供了范围广泛的数据库命令,覆盖了除create,read,update,delete之外的所有功能。比如我们前边用到的getLastError命令,用来查看update时受影响的数量。</p>     <p style="margin:5px auto;"><em>命令是如何工作的</em></p>     <p style="margin:5px auto;">这里有个你比较熟悉的例子:drop,如果从shell里删除一个collection,我们运行db.test.drop().实际上,在内部执行的是drop命令,跟下边用runCommand执行的操作是一样的</p>     <div style="border-bottom:#cccccc 1px solid;border-left:#cccccc 1px solid;padding-bottom:5px;overflow-x:auto;overflow-y:auto;background-color:#f5f5f5;padding-left:5px;padding-right:5px;font-family:'Courier New';font-size:12px;word-break:break-all;border-top:#cccccc 1px solid;border-right:#cccccc 1px solid;padding-top:5px;" class="cnblogs_code">      <pre style="margin-top:0px;font-family:'Courier New';word-wrap:break-word;white-space:pre-wrap;margin-bottom:0px;"><span style="line-height:1.5;">></span><span style="line-height:1.5;"> db.runCommand({</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">drop</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">test</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">}); {</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">nIndexesWas</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">1</span><span style="line-height:1.5;">,</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">msg</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">indexes dropped for collection</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">,</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">ns</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">test.test</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">,</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">ok</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;color:#0000ff;">true</span><span style="line-height:1.5;"> }</span></pre>     </div>     <p style="margin:5px auto;">作为结果返回的document叫做命令响应,包括了一些信息,如命令执行是否成功等。</p>     <p style="margin:5px auto;">实际上,mongoDB的命令被实现为一种对叫$cmd的collection的特殊查询,runCommand只是使用参数进行了一次查询,所以我们的drop也可以这样写</p>     <div style="border-bottom:#cccccc 1px solid;border-left:#cccccc 1px solid;padding-bottom:5px;overflow-x:auto;overflow-y:auto;background-color:#f5f5f5;padding-left:5px;padding-right:5px;font-family:'Courier New';font-size:12px;word-break:break-all;border-top:#cccccc 1px solid;border-right:#cccccc 1px solid;padding-top:5px;" class="cnblogs_code">      <pre style="margin-top:0px;font-family:'Courier New';word-wrap:break-word;white-space:pre-wrap;margin-bottom:0px;"><span style="line-height:1.5;">db.$cmd.findOne({</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">drop</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">test</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">});</span></pre>     </div>     <p style="margin:5px auto;">当mongoDB服务器接到一个对$cmd的查询时,使用一种特殊的逻辑来处理。几乎所有的驱动都提供了runCommand方法来执行命令,实际上这些命令都可以通过执行查询的方式来完成。</p>     <p style="margin:5px auto;"><em>命令参考</em></p>     <p style="margin:5px auto;">到目前mongoDB支持75个以上的数据库命令,而且这些命令越来越多,你可以通过两种方式查看支持的命令列表,一是在shell里执行 db.listCommands(),二是在浏览器里访问mongoDB的管理站点http://localhost:28017/_commands</p>     <p style="margin:5px auto;">下边列出了一些最常用的命令:</p>     <ul style="margin-left:45px;">      <li>buildInfo: {"buildInfo" : 1}, 返回mongoDB服务器版本和宿主操作系统的信息</li>      <li>collStats: {"collStats" : collection},给出指定collection的统计信息,包括数据大小,分配的存储控件,索引大小等</li>      <li>distinct: {"distinct" : collection, "key": key, "query": query} 返回在指定的collection里符合query条件的所有key的值</li>      <li>drop: {"drop" : collection}, 删除collection的说有数据</li>      <li>dropDatabase: {"dropDatabase" : 1}, 删除当前数据库的所有数据</li>      <li>dropIndexes: {"dropIndexes" : collection, "index" : name}, 删除collection上名字为name的索引</li>      <li>findAndModify:参见第3章</li>      <li>getLastError: {"getLastError" : 1[, "w" : w[, "wtimeout" : timeout]]}, 检查此连接上最后操作的错误或状态信息,可以指定一个选项,此命令将会阻塞直到w个salves复制了最后的那个操作或者时间超时(毫秒)</li>      <li>isMaster: {"isMaster" : 1}, 检查此服务器是master还是slave</li>      <li>listCommands: {"listCommands" : 1}, 列出此服务器上所有可用命令</li>      <li>listDatabases: {"listDatabases" : 1},列出服务器上所有数据库</li>      <li>ping: {"ping" : 1},检查服务器是否正在运行,即使服务器处于锁定状体此命令也会立即返回</li>      <li>renameCollection: {"renameCollection" : a, "to" : b}, 将collection的名字从a改为b</li>      <li>repairDatabase:{"repairDatabase" : 1}, 修复并压缩当前数据库</li>      <li>serverStatus:{"serverStatus" : 1}, 获取此服务器的管理统计信息</li>     </ul>     <p style="margin:5px auto;"><strong>2.Capped Collections</strong></p>     <p style="margin:5px auto;">mongoDB还支持一种特殊的collection叫Capped Collections,这种collection是事先创建并且是大小固定的。固定大小就带来了一个问题,如果collection满了之后对其执行插入该如何处理。Capped Collection的工作方式像一个循环队列,如果空间用完了,那么最旧的数据会被删除掉,新数据会取代旧数据的位置。这就是说,随着新 document的插入,最旧的document会自动消亡。</p>     <p style="margin:5px auto;">某些操作在Capped Collection上是不允许执行的。不允许执行document删除,也不允许执行会导致document移动的更新(使document变大的更新),这样就可以保证Capped Collections里的document是按照插入顺序存储的。</p>     <p style="margin:5px auto;"><em>特性和用例</em><strong><br /> </strong></p>     <p style="margin:5px auto;">Capped Collection的这些特点和限制会产生有趣的特性。首先是插入很快,执行插入的时候不再需要分配空间,服务器就不用查询空闲列表,插入的 document直接放在collection的尾部。缺省情况下,也不会更新索引,所以一次插入本质上就是一次内存拷贝。另外一个特性是,按插入顺序查询很快,document是按照插入顺序存储的,只需要按它们在磁盘上的顺序遍历。最后,旧数据的自动消亡也是个有用的特性。包括了上述3个特性的 Capped Collection对某些用例特别适用,如日志,实际上Capped Collection原本就是设计来存储内部复制日志的。另外还有个好的用例,缓存小规模的document。</p>     <p style="margin:5px auto;"><em>创建Capped Collections</em></p>     <div style="border-bottom:#cccccc 1px solid;border-left:#cccccc 1px solid;padding-bottom:5px;overflow-x:auto;overflow-y:auto;background-color:#f5f5f5;padding-left:5px;padding-right:5px;font-family:'Courier New';font-size:12px;word-break:break-all;border-top:#cccccc 1px solid;border-right:#cccccc 1px solid;padding-top:5px;" class="cnblogs_code">      <pre style="margin-top:0px;font-family:'Courier New';word-wrap:break-word;white-space:pre-wrap;margin-bottom:0px;"><span style="line-height:1.5;">></span><span style="line-height:1.5;"> db.createCollection(</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">my_collection</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">, {capped: </span><span style="line-height:1.5;color:#0000ff;">true</span><span style="line-height:1.5;">, size: </span><span style="line-height:1.5;">100000</span><span style="line-height:1.5;">}); { </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">ok</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;color:#0000ff;">true</span><span style="line-height:1.5;"> }</span></pre>     </div>     <p style="margin:5px auto;">另外还可以指定document的数量上限,如下</p>     <div style="border-bottom:#cccccc 1px solid;border-left:#cccccc 1px solid;padding-bottom:5px;overflow-x:auto;overflow-y:auto;background-color:#f5f5f5;padding-left:5px;padding-right:5px;font-family:'Courier New';font-size:12px;word-break:break-all;border-top:#cccccc 1px solid;border-right:#cccccc 1px solid;padding-top:5px;" class="cnblogs_code">      <pre style="margin-top:0px;font-family:'Courier New';word-wrap:break-word;white-space:pre-wrap;margin-bottom:0px;"><span style="line-height:1.5;">></span><span style="line-height:1.5;"> db.createCollection(</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">my_collection</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">, {capped: </span><span style="line-height:1.5;color:#0000ff;">true</span><span style="line-height:1.5;">, size: </span><span style="line-height:1.5;">100000</span><span style="line-height:1.5;">, max: </span><span style="line-height:1.5;">100</span><span style="line-height:1.5;">}); { </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">ok</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;color:#0000ff;">true</span><span style="line-height:1.5;"> }</span></pre>     </div>     <p style="margin:5px auto;">将一个普通collection转化为Capped Collection</p>     <div style="border-bottom:#cccccc 1px solid;border-left:#cccccc 1px solid;padding-bottom:5px;overflow-x:auto;overflow-y:auto;background-color:#f5f5f5;padding-left:5px;padding-right:5px;font-family:'Courier New';font-size:12px;word-break:break-all;border-top:#cccccc 1px solid;border-right:#cccccc 1px solid;padding-top:5px;" class="cnblogs_code">      <pre style="margin-top:0px;font-family:'Courier New';word-wrap:break-word;white-space:pre-wrap;margin-bottom:0px;"><span style="line-height:1.5;">></span><span style="line-height:1.5;"> db.runCommand({convertToCapped: </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">test</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">, size: </span><span style="line-height:1.5;">10000</span><span style="line-height:1.5;">}); { </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">ok</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;color:#0000ff;">true</span><span style="line-height:1.5;"> }</span></pre>     </div>     <p style="margin:5px auto;"><em>自然排序</em></p>     <p style="margin:5px auto;">自然排序是Capped Collection上的一种特殊排序,就是按照磁盘上的存储顺序排序。当然也可以按反存储顺序排序,指定参数-1.</p>     <div style="border-bottom:#cccccc 1px solid;border-left:#cccccc 1px solid;padding-bottom:5px;overflow-x:auto;overflow-y:auto;background-color:#f5f5f5;padding-left:5px;padding-right:5px;font-family:'Courier New';font-size:12px;word-break:break-all;border-top:#cccccc 1px solid;border-right:#cccccc 1px solid;padding-top:5px;" class="cnblogs_code">      <pre style="margin-top:0px;font-family:'Courier New';word-wrap:break-word;white-space:pre-wrap;margin-bottom:0px;"><span style="line-height:1.5;">></span><span style="line-height:1.5;"> db.my_collection.find().sort({</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">$natural</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">-</span><span style="line-height:1.5;">1</span><span style="line-height:1.5;">})</span></pre>     </div>     <p style="margin:5px auto;"><em>循环游标(Tailable Cursors)</em></p>     <p style="margin:5px auto;">循环游标只能用于Capped Collection上,循环游标是一种特殊的持久性的游标,在结果集耗尽之后并不会关闭,当有了新document插入到collection之后,它可以继续取出。shell不支持循环游标。</p>     <p style="margin:5px auto;"><strong>3.GridFS: 存储文件</strong></p>     <p style="margin:5px auto;">GridFS是mongoDB里的存储二进制大文件的机制。使用GridFS最简单的方式就是使用mongofiles工具,这个工具在分发包里边有。下边演示了如何使用mongofiles上传下载列出文件。</p>     <div style="border-bottom:#cccccc 1px solid;border-left:#cccccc 1px solid;padding-bottom:5px;overflow-x:auto;overflow-y:auto;background-color:#f5f5f5;padding-left:5px;padding-right:5px;font-family:'Courier New';font-size:12px;word-break:break-all;border-top:#cccccc 1px solid;border-right:#cccccc 1px solid;padding-top:5px;" class="cnblogs_code">      <pre style="margin-top:0px;font-family:'Courier New';word-wrap:break-word;white-space:pre-wrap;margin-bottom:0px;"><span style="line-height:1.5;">$ echo </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">Hello, world</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> </span><span style="line-height:1.5;">></span><span style="line-height:1.5;"> foo.txt $ .</span><span style="line-height:1.5;">/</span><span style="line-height:1.5;">mongofiles put foo.txt</span><span style="line-height:1.5;"> </span><span style="line-height:1.5;">connected to: </span><span style="line-height:1.5;">127.0</span><span style="line-height:1.5;">.</span><span style="line-height:1.5;">0.1</span><span style="line-height:1.5;"> added file: { _id: ObjectId(</span><span style="line-height:1.5;">'</span><span style="line-height:1.5;">4c0d2a6c3052c25545139b88</span><span style="line-height:1.5;">'</span><span style="line-height:1.5;">), filename: </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">foo.txt</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">, length: </span><span style="line-height:1.5;">13</span><span style="line-height:1.5;">, chunkSize: </span><span style="line-height:1.5;">262144</span><span style="line-height:1.5;">, uploadDate: </span><span style="line-height:1.5;color:#0000ff;">new</span><span style="line-height:1.5;"> Date(</span><span style="line-height:1.5;">1275931244818</span><span style="line-height:1.5;">), md5: </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">a7966bf58e23583c9a5a4059383ff850</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> } done</span><span style="line-height:1.5;">!</span><span style="line-height:1.5;"> $ .</span><span style="line-height:1.5;">/</span><span style="line-height:1.5;">mongofiles list</span><span style="line-height:1.5;"> </span><span style="line-height:1.5;">connected to: </span><span style="line-height:1.5;">127.0</span><span style="line-height:1.5;">.</span><span style="line-height:1.5;">0.1</span><span style="line-height:1.5;"> foo.txt </span><span style="line-height:1.5;">13</span><span style="line-height:1.5;"> $ rm foo.txt $ .</span><span style="line-height:1.5;">/</span><span style="line-height:1.5;">mongofiles get foo.txt</span><span style="line-height:1.5;"> </span><span style="line-height:1.5;">connected to: </span><span style="line-height:1.5;">127.0</span><span style="line-height:1.5;">.</span><span style="line-height:1.5;">0.1</span><span style="line-height:1.5;"> done write to: foo.txt $ cat foo.txt Hello, world</span></pre>     </div>     <p style="margin:5px auto;">ps:如果你使用的是windows控制台,需要把rm命令换成del,把cat命令换成type</p>     <p style="margin:5px auto;">mongofiles还支持search和delete。</p>     <p style="margin:5px auto;">GridFS是一个基于普通document之上的文件存储规范,mongoDB服务器对GridFS请求几乎没有做任何特殊处理,所有的工作都是客户端驱动和工具完成的。</p>     <p style="margin:5px auto;">GridFS的基本思想是将大文件分割成多个块,每个块存储为一个document,除了存储文件的每个块外,还有个单独的document把这些块组织在一起,并且包含了文件的元数据信息。</p>     <p style="margin:5px auto;">GridFS中的块有自己的collection,缺省是使用fs.chunks,文件元数据存储在另外一个collection,缺省为fs.files。</p>     <p style="margin:5px auto;"><strong>4.服务器端脚本</strong></p>     <p style="margin:5px auto;">db.eval函数允许你在服务器端执行javascript代码,将javascript字符串传递给服务器,然后返回结果。</p>     <p style="margin:5px auto;">db.eval可以用来模拟事务,db.eval会锁定数据库,执行javascript,然后解锁数据库。虽然没有回滚,这也能够让你保证一组操作是按顺序执行。</p>     <p style="margin:5px auto;">代码可以包装进一个function发送也可以不包装,下边两行是等价的</p>     <div style="border-bottom:#cccccc 1px solid;border-left:#cccccc 1px solid;padding-bottom:5px;overflow-x:auto;overflow-y:auto;background-color:#f5f5f5;padding-left:5px;padding-right:5px;font-family:'Courier New';font-size:12px;word-break:break-all;border-top:#cccccc 1px solid;border-right:#cccccc 1px solid;padding-top:5px;" class="cnblogs_code">      <pre style="margin-top:0px;font-family:'Courier New';word-wrap:break-word;white-space:pre-wrap;margin-bottom:0px;"><span style="line-height:1.5;">></span><span style="line-height:1.5;"> db.eval(</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">return 1;</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">)</span><span style="line-height:1.5;">1</span><span style="line-height:1.5;"> </span><span style="line-height:1.5;">></span><span style="line-height:1.5;"> db.eval(</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">function() { return 1; }</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">)</span><span style="line-height:1.5;">1</span></pre>     </div>     <p style="margin:5px auto;">如果要传递参数的话,就必须将代码封装进函数了</p>     <div style="border-bottom:#cccccc 1px solid;border-left:#cccccc 1px solid;padding-bottom:5px;overflow-x:auto;overflow-y:auto;background-color:#f5f5f5;padding-left:5px;padding-right:5px;font-family:'Courier New';font-size:12px;word-break:break-all;border-top:#cccccc 1px solid;border-right:#cccccc 1px solid;padding-top:5px;" class="cnblogs_code">      <pre style="margin-top:0px;font-family:'Courier New';word-wrap:break-word;white-space:pre-wrap;margin-bottom:0px;"><span style="line-height:1.5;">></span><span style="line-height:1.5;"> db.eval(</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">function(x,y,z) { return x + y + z; }</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">, [num1, num2, num3])</span></pre>     </div>     <p style="margin:5px auto;"><em>Stored Javascript</em></p>     <p style="margin:5px auto;">mongoDB里的每个数据库都有个特殊的collection叫system.js,用于存储javascript变量,这些变量可以在任意的 javascript上下文中使用,包括"$where"子句、db.eval调用、MapReduce任务等。通过简单的插入就可以添加 javascript变量了。</p>     <div style="border-bottom:#cccccc 1px solid;border-left:#cccccc 1px solid;padding-bottom:5px;overflow-x:auto;overflow-y:auto;background-color:#f5f5f5;padding-left:5px;padding-right:5px;font-family:'Courier New';font-size:12px;word-break:break-all;border-top:#cccccc 1px solid;border-right:#cccccc 1px solid;padding-top:5px;" class="cnblogs_code">      <pre style="margin-top:0px;font-family:'Courier New';word-wrap:break-word;white-space:pre-wrap;margin-bottom:0px;"><span style="line-height:1.5;">></span><span style="line-height:1.5;"> db.system.js.insert({</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">_id</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">x</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">, </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">value</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">1</span><span style="line-height:1.5;">})</span><span style="line-height:1.5;">></span><span style="line-height:1.5;"> db.system.js.insert({</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">_id</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">y</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">, </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">value</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">2</span><span style="line-height:1.5;">})</span><span style="line-height:1.5;">></span><span style="line-height:1.5;"> db.system.js.insert({</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">_id</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">z</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">, </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">value</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">3</span><span style="line-height:1.5;">})</span></pre>     </div>     <p style="margin:5px auto;">这样就在全局范围定义了x、y、z三个变量,如果你想求它们的和</p>     <div style="border-bottom:#cccccc 1px solid;border-left:#cccccc 1px solid;padding-bottom:5px;overflow-x:auto;overflow-y:auto;background-color:#f5f5f5;padding-left:5px;padding-right:5px;font-family:'Courier New';font-size:12px;word-break:break-all;border-top:#cccccc 1px solid;border-right:#cccccc 1px solid;padding-top:5px;" class="cnblogs_code">      <pre style="margin-top:0px;font-family:'Courier New';word-wrap:break-word;white-space:pre-wrap;margin-bottom:0px;"><span style="line-height:1.5;">></span><span style="line-height:1.5;"> db.eval(</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">return x+y+z;</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">)</span><span style="line-height:1.5;">6</span></pre>     </div>     <p style="margin:5px auto;">system.js同样可以存储javascript代码,例如,你想创建一个日志打印函数</p>     <div style="border-bottom:#cccccc 1px solid;border-left:#cccccc 1px solid;padding-bottom:5px;overflow-x:auto;overflow-y:auto;background-color:#f5f5f5;padding-left:5px;padding-right:5px;font-family:'Courier New';font-size:12px;word-break:break-all;border-top:#cccccc 1px solid;border-right:#cccccc 1px solid;padding-top:5px;" class="cnblogs_code">      <pre style="margin-top:0px;font-family:'Courier New';word-wrap:break-word;white-space:pre-wrap;margin-bottom:0px;"><span style="line-height:1.5;">></span><span style="line-height:1.5;"> db.system.js.insert({</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">_id</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">log</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">, </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">value</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : ... </span><span style="line-height:1.5;color:#0000ff;">function</span><span style="line-height:1.5;">(msg, level) { ... </span><span style="line-height:1.5;color:#0000ff;">  var</span><span style="line-height:1.5;"> levels </span><span style="line-height:1.5;">=</span><span style="line-height:1.5;"> [</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">DEBUG</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">, </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">WARN</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">, </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">ERROR</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">, </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">FATAL</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">]; ...   level </span><span style="line-height:1.5;">=</span><span style="line-height:1.5;"> level </span><span style="line-height:1.5;">?</span><span style="line-height:1.5;"> level : </span><span style="line-height:1.5;">0</span><span style="line-height:1.5;">; </span><span style="line-height:1.5;color:#008000;">//</span><span style="line-height:1.5;color:#008000;"> check if level is defined</span><span style="line-height:1.5;color:#008000;"> </span><span style="line-height:1.5;">... </span><span style="line-height:1.5;color:#0000ff;">  var</span><span style="line-height:1.5;"> now </span><span style="line-height:1.5;">=</span><span style="line-height:1.5;"> </span><span style="line-height:1.5;color:#0000ff;">new</span><span style="line-height:1.5;"> Date(); ...   print(now </span><span style="line-height:1.5;">+</span><span style="line-height:1.5;"> </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> </span><span style="line-height:1.5;">+</span><span style="line-height:1.5;"> levels[level] </span><span style="line-height:1.5;">+</span><span style="line-height:1.5;"> msg); ... }})</span></pre>     </div>     <p style="margin:5px auto;">那么你就可以在任何javascript上下文中调用此函数了</p>     <div style="border-bottom:#cccccc 1px solid;border-left:#cccccc 1px solid;padding-bottom:5px;overflow-x:auto;overflow-y:auto;background-color:#f5f5f5;padding-left:5px;padding-right:5px;font-family:'Courier New';font-size:12px;word-break:break-all;border-top:#cccccc 1px solid;border-right:#cccccc 1px solid;padding-top:5px;" class="cnblogs_code">      <pre style="margin-top:0px;font-family:'Courier New';word-wrap:break-word;white-space:pre-wrap;margin-bottom:0px;"><span style="line-height:1.5;">></span><span style="line-height:1.5;"> db.eval(</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">x = 1; log('x is '+x); x = 2; log('x is greater than 1', 1);</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">);</span></pre>     </div>     <p style="margin:5px auto;">数据库日志中就会包含下边的内容</p>     <p style="margin:5px auto;">Fri Jun 11 2010 11:12:39 GMT-0400 (EST) DEBUG x is 1<br /> Fri Jun 11 2010 11:12:40 GMT-0400 (EST) WARN x is greater than 1</p>     <p style="margin:5px auto;"><strong>5.数据库引用</strong>(Database References/DBRef)</p>     <p style="margin:5px auto;">一个DBRef就是一个嵌入的document,和其他的嵌入document一样,但是必须有一些特殊的key。如下</p>     <div style="border-bottom:#cccccc 1px solid;border-left:#cccccc 1px solid;padding-bottom:5px;overflow-x:auto;overflow-y:auto;background-color:#f5f5f5;padding-left:5px;padding-right:5px;font-family:'Courier New';font-size:12px;word-break:break-all;border-top:#cccccc 1px solid;border-right:#cccccc 1px solid;padding-top:5px;" class="cnblogs_code">      <pre style="margin-top:0px;font-family:'Courier New';word-wrap:break-word;white-space:pre-wrap;margin-bottom:0px;"><span style="line-height:1.5;">{</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">$ref</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : collection, </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">$id</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : id_value}</span></pre>     </div>     <p style="margin:5px auto;">这个DBRef引用了collection和id_value,使用这两个值就可以唯一确定一个document。如果要引用其他数据库的document,还需要第三个key,即"$db"</p>     <div style="border-bottom:#cccccc 1px solid;border-left:#cccccc 1px solid;padding-bottom:5px;overflow-x:auto;overflow-y:auto;background-color:#f5f5f5;padding-left:5px;padding-right:5px;font-family:'Courier New';font-size:12px;word-break:break-all;border-top:#cccccc 1px solid;border-right:#cccccc 1px solid;padding-top:5px;" class="cnblogs_code">      <pre style="margin-top:0px;font-family:'Courier New';word-wrap:break-word;white-space:pre-wrap;margin-bottom:0px;"><span style="line-height:1.5;">{</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">$ref</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : collection, </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">$id</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : id_value, </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">$db</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : database}</span></pre>     </div>     <p style="margin:5px auto;">Note:DBRef里边的key的顺序是有影响的,第一个必须是"$ref",然后是"$id",然后是可选的"$db"。</p>     <p style="margin:5px auto;">由于mongoDB是非关系型的(无join),document之间的引用(外键)通常是客户端通过额外的查询来完成的。mongoDB里有两种常用的做法,一是简单的手动引用,另外就是DBRef标准,很多驱动都是支持DBRef的。</p>     <p style="margin:5px auto;"><em>简单的手动引用</em></p>     <p style="margin:5px auto;">一般来说,手动写代码来处理引用的办法用起来还是不错的,我们只需要把另外的document的_id的值存起来,然后进行查询,如:</p>     <div style="border-bottom:#cccccc 1px solid;border-left:#cccccc 1px solid;padding-bottom:5px;overflow-x:auto;overflow-y:auto;background-color:#f5f5f5;padding-left:5px;padding-right:5px;font-family:'Courier New';font-size:12px;word-break:break-all;border-top:#cccccc 1px solid;border-right:#cccccc 1px solid;padding-top:5px;" class="cnblogs_code">      <pre style="margin-top:0px;font-family:'Courier New';word-wrap:break-word;white-space:pre-wrap;margin-bottom:0px;"><span style="line-height:1.5;">></span><span style="line-height:1.5;"> </span><span style="line-height:1.5;color:#008000;">//</span><span style="line-height:1.5;color:#008000;"> grab a random blog post:</span><span style="line-height:1.5;color:#008000;"> </span><span style="line-height:1.5;">></span><span style="line-height:1.5;"> p </span><span style="line-height:1.5;">=</span><span style="line-height:1.5;"> db.postings.findOne(); {     </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">_id</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : ObjectId(</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">4b866f08234ae01d21d89604</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">),     </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">author</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">jim</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">,     </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">title</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">Brewing Methods</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> }</span><span style="line-height:1.5;">></span><span style="line-height:1.5;"> </span><span style="line-height:1.5;color:#008000;">//</span><span style="line-height:1.5;color:#008000;"> get more info on author of post p</span><span style="line-height:1.5;color:#008000;"> </span><span style="line-height:1.5;">></span><span style="line-height:1.5;"> a </span><span style="line-height:1.5;">=</span><span style="line-height:1.5;"> db.users.findOne( { _id : p.author } ) { </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">_id</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">jim</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">, </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">email</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">jim@gmail.com</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> }</span><span style="line-height:1.5;">></span><span style="line-height:1.5;"> </span><span style="line-height:1.5;color:#008000;">//</span><span style="line-height:1.5;color:#008000;"> inverse: given an author, find all blog posts for the author</span><span style="line-height:1.5;color:#008000;"> </span><span style="line-height:1.5;">></span><span style="line-height:1.5;"> db.postings.find( {author : a._id } )</span></pre>     </div>     <p style="margin:5px auto;"><em>DBRef</em></p>     <p style="margin:5px auto;">各个驱动对DBRef的实现不太一样,不是所有的驱动都把DBRef当成普通的嵌入document,有些提供了一个特殊类型来自动转换。C#中使用一个叫DBRef的类,构造函数有两个参数,collection的名字和_id,然后就可以用FollowReference方法来获取引用的 document。</p>     <p style="margin:5px auto;">在javascript(shell)中,如下例:</p>     <div style="border-bottom:#cccccc 1px solid;border-left:#cccccc 1px solid;padding-bottom:5px;overflow-x:auto;overflow-y:auto;background-color:#f5f5f5;padding-left:5px;padding-right:5px;font-family:'Courier New';font-size:12px;word-break:break-all;border-top:#cccccc 1px solid;border-right:#cccccc 1px solid;padding-top:5px;" class="cnblogs_code">      <pre style="margin-top:0px;font-family:'Courier New';word-wrap:break-word;white-space:pre-wrap;margin-bottom:0px;"><span style="line-height:1.5;">></span><span style="line-height:1.5;"> x </span><span style="line-height:1.5;">=</span><span style="line-height:1.5;"> { name : </span><span style="line-height:1.5;">'</span><span style="line-height:1.5;">Biology</span><span style="line-height:1.5;">'</span><span style="line-height:1.5;"> } { </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">name</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">Biology</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> }</span><span style="line-height:1.5;">></span><span style="line-height:1.5;"> db.courses.save(x)</span><span style="line-height:1.5;">></span><span style="line-height:1.5;"> x { </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">name</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">Biology</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">, </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">_id</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : ObjectId(</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">4b0552b0f0da7d1eb6f126a1</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">) }</span><span style="line-height:1.5;">></span><span style="line-height:1.5;"> stu </span><span style="line-height:1.5;">=</span><span style="line-height:1.5;"> { name : </span><span style="line-height:1.5;">'</span><span style="line-height:1.5;">Joe</span><span style="line-height:1.5;">'</span><span style="line-height:1.5;">, classes : [ </span><span style="line-height:1.5;color:#0000ff;">new</span><span style="line-height:1.5;"> DBRef(</span><span style="line-height:1.5;">'</span><span style="line-height:1.5;">courses</span><span style="line-height:1.5;">'</span><span style="line-height:1.5;">, x._id) ] }</span><span style="line-height:1.5;color:#008000;">//</span><span style="line-height:1.5;color:#008000;"> or we could write:</span><span style="line-height:1.5;color:#008000;"> //</span><span style="line-height:1.5;color:#008000;"> stu = { name : 'Joe', classes : [ {$ref:'courses',$id:x._id} ] }</span><span style="line-height:1.5;color:#008000;"> </span><span style="line-height:1.5;">></span><span style="line-height:1.5;"> db.students.save(stu)</span><span style="line-height:1.5;">></span><span style="line-height:1.5;"> stu {         </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">name</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">Joe</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">,         </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">classes</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : [                 {                         </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">$ref</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">courses</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">,                         </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">$id</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : ObjectId(</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">4b0552b0f0da7d1eb6f126a1</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">)                 }         ],         </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">_id</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : ObjectId(</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">4b0552e4f0da7d1eb6f126a2</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">) }</span><span style="line-height:1.5;">></span><span style="line-height:1.5;"> stu.classes[</span><span style="line-height:1.5;">0</span><span style="line-height:1.5;">] { </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">$ref</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">courses</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">, </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">$id</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : ObjectId(</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">4b0552b0f0da7d1eb6f126a1</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">) }</span><span style="line-height:1.5;">></span><span style="line-height:1.5;"> stu.classes[</span><span style="line-height:1.5;">0</span><span style="line-height:1.5;">].fetch() { </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">_id</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : ObjectId(</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">4b0552b0f0da7d1eb6f126a1</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">), </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">name</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> : </span><span style="line-height:1.5;">"</span><span style="line-height:1.5;">Biology</span><span style="line-height:1.5;">"</span><span style="line-height:1.5;"> }</span><span style="line-height:1.5;">></span></pre>     </div>     <p style="margin:5px auto;"></p>    </div>