搜索
您的当前位置:首页正文

MongoDB若基本操作

来源:小奈知识网


启动数据库

下载 MongoDB, 解压后并启动:

代码

 

$ bin/mongod

MongoDB 默认存储数据目录为 /data/db/ (或者 c:\\data\\db), 当然你也可以修改成不同目录, 只需要指定 –dbpath 参数:

代码

 

$ bin/mongod --dbpath /path/to/my/data/dir

获取数据库连接

现在我们就可以使用自带的shell工具来操作数据库了. (我们也可以使用各种编程语言的驱动来使用MongoDB, 自带的shell工具可以方便我们管理数据库)

启动 MongoDB JavaScript 工具:

代码

 

$ bin/mongo

默认 shell 连接的是本机localhost 上面的 test库, 会看到:

代码

         

MongoDB shell version: 0.9.8

url: test

connecting to: test

type \"help\" for help >

“connecting to:” 这个会显示你正在使用的数据库的名称. 想换数据库的话可以:

代码



 > use mydb

可以输入 help 来查看所有的命令.

插入数据到集合

下面我们来建立一个test的集合并写入一些数据. 建立两个对象, j 和 t , 并保存到集合中去. 在例子里 „>‟ 来表示是 shell 输入提示符

代码



                   > j = { name : \"mongo\" };

{\"name\" : \"mongo\

> t = { x : 3 };

{ \"x\" : 3 }

> db.things.save(j);

> db.things.save(t);

> db.things.find();

{\"name\" : \"mongo\" , \"_id\" : ObjectId(\"497cf60751712cf7758fbdbb\")}

{\"x\" : 3 , \"_id\" : ObjectId(\"497cf61651712cf7758fbdbc\")} >

有几点需要注意下 :

a.不需要预先建立一个集合. 在第一次插入数据时候会自动建立.

b.在例子其实可以存储任何结构的数据, 当然在实际应用我们存储的还是相同元素的集合. 这个特性其实可以在应用里很灵活, 你不需要类似alter table 来修改你的数据结构 c.每次插入数据时候对象都会有一个ID, 名字叫 _id. d.当你运行不同的例子, 你的对象ID值都是不同的.

下面再加点数据:

代码



 > for( var i = 1; i < 10; i++ ) db.things.save( { x:4, j:i } ); > db.things.find(); 

 {\"name\" : \"mongo\" , \"_id\" : ObjectId(\"497cf60751712cf7758fbdbb\")} 

 {\"x\" : 3 , \"_id\" : ObjectId(\"497cf61651712cf7758fbdbc\")} 

 {\"x\" : 4 , \"j\" : 1 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdbd\")} 

 {\"x\" : 4 , \"j\" : 2 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdbe\")} 

 {\"x\" : 4 , \"j\" : 3 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdbf\")} 

 {\"x\" : 4 , \"j\" : 4 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc0\")} 

 {\"x\" : 4 , \"j\" : 5 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc1\")} 

 {\"x\" : 4 , \"j\" : 6 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc2\")} 

 {\"x\" : 4 , \"j\" : 7 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc3\")} 

 {\"x\" : 4 , \"j\" : 8 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc4\")}

请注意下, 这里循环次数是10, 但是只显示到8, 还有2条数据没有显示.

如果想继续查询下面的数据只需要使用 it 命令, 就会继续下面的数据:

代码

   

{\"x\" : 4 , \"j\" : 7 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc3\")}

{\"x\" : 4 , \"j\" : 8 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc4\")}

继续

代码

     

> it

{\"x\" : 4 , \"j\" : 9 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc5\")}

{\"x\" : 4 , \"j\" : 10 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc6\")}

从技术上讲 find() 返回一个游标对象. 但在上面的例子里, 并没有拿到一个游标的变量. 所以 shell 自动遍历游标, 返回一个初始化的set, 并允许我们继续用 it 迭代输出. 当然我们也可以直接用游标来输出, 不过这个是下一部分的内容了.

查询数据

在没有深入查询之前, 我们先看看怎么从一个查询中返回一个游标对象. 可以简单的通过 find() 来查询, 他返回一个任意结构的集合. 如果实现特定的查询稍后讲解. 实现上面同样的查询, 然后通过 while 来输出:

代码

                    

> var cursor = db.things.find();

> while (cursor.hasNext()) { print(tojson(cursor.next())); }

{\"name\" : \"mongo\" , \"_id\" : ObjectId(\"497cf60751712cf7758fbdbb\")}

{\"x\" : 3 , \"_id\" : ObjectId(\"497cf61651712cf7758fbdbc\")}

{\"x\" : 4 , \"j\" : 1 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdbd\")}

{\"x\" : 4 , \"j\" : 2 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdbe\")}

{\"x\" : 4 , \"j\" : 3 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdbf\")}

{\"x\" : 4 , \"j\" : 4 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc0\")}

{\"x\" : 4 , \"j\" : 5 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc1\")}

{\"x\" : 4 , \"j\" : 6 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc2\")}

       {\"x\" : 4 , \"j\" : 7 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc3\")}

{\"x\" : 4 , \"j\" : 8 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc4\")}

{\"x\" : 4 , \"j\" : 9 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc5\")} >

上面的例子显示了游标风格的迭代输出. hasNext() 函数告诉我们是否还有数据, 如果有则可以调用 next() 函数. 这里我们也用了自带的 tojson() 方法返回一个标准的 JSON 格式数据.

当我们使用的是 JavaScript shell, 可以用到JS的特性, forEach 就可以输出游标了. 下面的例子就是使用 forEach() 来循环输出:

forEach() 必须定义一个函数供每个游标元素调用.

代码



 > db.things.find().forEach( function(x) { print(tojson(x));}); 

 {\"name\" : \"mongo\" , \"_id\" : ObjectId(\"497cf60751712cf7758fbdbb\")} 

 {\"x\" : 3 , \"_id\" : ObjectId(\"497cf61651712cf7758fbdbc\")} 

 {\"x\" : 4 , \"j\" : 1 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdbd\")} 

 {\"x\" : 4 , \"j\" : 2 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdbe\")} 

 {\"x\" : 4 , \"j\" : 3 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdbf\")} 

 {\"x\" : 4 , \"j\" : 4 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc0\")} 

 {\"x\" : 4 , \"j\" : 5 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc1\")} 

 {\"x\" : 4 , \"j\" : 6 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc2\")} 

 {\"x\" : 4 , \"j\" : 7 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc3\")} 

 {\"x\" : 4 , \"j\" : 8 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc4\")} 

 {\"x\" : 4 , \"j\" : 9 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc5\")}   >

在 mongo shell 里, 我们也可以把游标当作数组来用 :

代码



 > var cursor = db.things.find(); 

 > print (tojson(cursor[4])); 

 {\"x\" : 4 , \"j\" : 3 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdbf\")}

使用游标时候请注意占用内存的问题, 特别是很大的游标对象, 有可能会内存溢出. 所以应该用迭代的方式来输出.

下面的示例则是把游标转换成真实的数组类型:

代码



 > var arr = db.things.find().toArray(); 

 > arr[5]; 

 {\"x\" : 4 , \"j\" : 4 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc0\")}

请注意这些特性只是在 mongo shell 里使用, 而不是所有的其他应用程序驱动都支持.

MongoDB 游标对象不是没有快照 – 如果有其他用户在集合里第一次或者最后一次调用 next(), 你可以得不到游标里的数据. 所以要明确的锁定你要查询的游标.

指定条件的查询

到这里我们已经知道怎么从游标里实现一个查询并返回数据对象, 下面就来看看怎么根据指定的条件来查询.

下面的示例就是说明如何执行一个类似SQL的查询, 并演示了怎么在 MongoDB 里实现. 这是在 MongoDB shell 里查询, 当然你也可以用其他的应用驱动或者语言来实现:

代码



 SELECT * FROM things WHERE name=\"mongo\">

db.things.find({name:\"mongo\ 

 {\"name\" : \"mongo\" , \"_id\" : ObjectId(\"497cf60751712cf7758fbdbb\")} 

 >SELECT * FROM things WHERE x=4> db.things.find({x:4}).forEach(function(x) { print(tojson(x));});

 {\"x\" : 4 , \"j\" : 1 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdbd\")} 

 {\"x\" : 4 , \"j\" : 2 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdbe\")} 

 {\"x\" : 4 , \"j\" : 3 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdbf\")} 

 {\"x\" : 4 , \"j\" : 4 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc0\")} 

 {\"x\" : 4 , \"j\" : 5 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc1\")} 

 {\"x\" : 4 , \"j\" : 6 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc2\")} 

 {\"x\" : 4 , \"j\" : 7 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc3\")} 

 {\"x\" : 4 , \"j\" : 8 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc4\")} 

 {\"x\" : 4 , \"j\" : 9 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc5\")}   >

查询条件是 { a:A, b:B, … } 类似 “where a==A and b==B and …”, 更多的查询方式可以参考 Mongo 开发教程部分.

上面显示的是所有的元素, 当然我们也可以返回特定的元素, 类似于返回表里某字段的值, 只需要在 find({x:4}) 里指定元素的名字, 比如 j:

代码



 SELECT j FROM things WHERE x=4> db.things.find({x:4}, {j:true}).forEach(function(x) { print(tojson(x));}); 

 {\"j\" : 1 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdbd\")} 

 {\"j\" : 2 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdbe\")} 

 {\"j\" : 3 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdbf\")} 

 {\"j\" : 4 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc0\")} 

 {\"j\" : 5 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc1\")} 

 {\"j\" : 6 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc2\")} 

 {\"j\" : 7 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc3\")} 

 {\"j\" : 8 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc4\")} 

 {\"j\" : 9 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdc5\")}   >

请注意 “_id” 元素会一直被返回.

findOne() – 语法糖

为了方便, mongo shell (其他驱动) 避免游标的可能带来的开销, 提供一个findOne() 函数. 这个函数和 find() 参数一样, 不过他返回游标里第一条数据, 或者返回 null 空数据库.

作为一个例子, name==‟mongo‟ 可以用很多方法来实现, 可以用 next() 来循环游标(需要校验是否为null), 或者当做数组返回第一个元素.

但是用 findOne() 方法则更简单和高效:

代码



 > var mongo = db.things.findOne({name:\"mongo\ 

 > print(tojson(mongo)); 

 {\"name\" : \"mongo\" , \"_id\" : ObjectId(\"497cf60751712cf7758fbdbb\")}   >

findOne 方法更跟 find({name:”mongo”}).limit(1) 一样.

limit() 查询

你可以需要限制结果集的长度, 可以调用 limit 方法.

这是强烈推荐高性能的原因, 通过限制条数来减少网络传输, 例如:

代码



 > db.things.find().limit(3); 

 in cursor for : DBQuery: example.things -> 

 {\"name\" : \"mongo\" , \"_id\" : ObjectId(\"497cf60751712cf7758fbdbb\")} 

 {\"x\" : 3 , \"_id\" : ObjectId(\"497cf61651712cf7758fbdbc\")} 

 {\"x\" : 4 , \"j\" : 1 , \"_id\" : ObjectId(\"497cf87151712cf7758fbdbd\")}   >

更多帮助

除非了一般的 help 之外, 你还可以查询 help 数据库和db.whatever 来查询具体的说明.

如果你对一个函数要做什么, 你可以不输入 {{()}} 这些结束的括号则可以输出实现的源码, 例如:

代码



 > db.foo.insert 

 function (obj, _allow_dot) { 

 if (!obj) { 

 throw \"no object passed to insert!\";   } 

 if (!_allow_dot) { 

 this._validateForStorage(obj);   } 

 return this._mongo.insert(this._fullName, obj);   }

mongo 是一个完整的 JavaScript shell程序, 所以在 shell 里完全可以私用JS的方法、类、语法. 此外, MongoDB 定义很多自己的类和全局变量 (比如 db). 这里可以查看完整的API说明 http://api.mongodb.org/js/.

Mongo Database 性能优化

推荐

博客园- 自由、创新、研究、探索

作者: geff zhang 发表于 2010-10-02 16:36 原文链接 阅读: 27 评论: 0

SQL Server有工具进行数据库的优化,Mongo Database Profiler.不仅有,而且功能更强大。 MongoDB 自带 Profiler,可以非常方便地记录下所有耗时过长操作,以便于调优。有两种方式可以控制 Profiling 的开关和级别,第一种是直接在启动参数里直接进行设置。 启动MongoDB时加上–profile=级别 即可。

也可以在客户端调用db.setProfilingLevel(级别) 命令来实时配置。可以通过db.getProfilingLevel()命令来获取当前的Profile级别。 1 > db.setProfilingLevel(2); 2 {\"was\" : 0 , \"ok\" : 1} 3 > db.getProfilingLevel() 上面斜体的级别可以取0,1,2 三个值,他们表示的意义如下:

0 – 不开启,关闭性能分析,测试环境可以打开,生成环境关闭,对性能有很大影响 1 – 记录慢命令 (默认为>100ms) 2 – 记录所有命令

Profile 记录在级别1时会记录慢命令,那么这个慢的定义是什么?上面我们说到其默认为

100ms,当然有默认就有设置,其设置方法和级别一样有两种,一种是通过添加–slowms启动参数配置。第二种是调用db.setProfilingLevel时加上第二个参数: 1 db.setProfilingLevel( level , slowms ) 2 db.setProfilingLevel( 1 , 10 );

Profiler 信息保存在 system.profile (Capped Collection) 中。也可以通过这个工具进行设置和查看数据:强大的MongoDB数据库管理工具

Mongo Shell 还提供了一个比较简洁的命令show profile,可列出最近5条执行时间超过1ms的 Profile 记录。

查看当前库下所有集合的分析数据 db.system.profile.find() 查看某一个集合的分析数据

db.system.profile.find({info:/user.info/})

查看执行时间大于100毫秒的执行操作,并倒序排列,并取前5行

db.system.profile.find({millis:{$gt:100}}).sort({$natural:-1}).limit(5); Profile 信息内容详解: ts-该命令在何时执行.

millis Time-该命令执行耗时,以毫秒记. info-本命令的详细信息.

query-表明这是一个query查询操作.

ntoreturn-本次查询客户端要求返回的记录数.比如, findOne()命令执行时 ntoreturn 为 1.有limit(n) 条件时ntoreturn为n. query-具体的查询条件(如x>3). nscanned-本次查询扫描的记录数. reslen-返回结果集的大小.

nreturned-本次查询实际返回的结果集. update-表明这是一个update更新操作.

fastmod-Indicates a fast modify operation. See Updates. These operations are normally quite fast.

fastmodinsert – indicates a fast modify operation that performed an upsert.

upsert-表明update的upsert参数为true.此参数的功能是如果update的记录不存在,则用update的条件insert一条记录.

moved-表明本次update是否移动了硬盘上的数据,如果新记录比原记录短,通常不会移动当前记录,如果新记录比原记录长,那么可能会移动记录到其它位置,这时候会导致相关索引的更新.磁盘操作更多,加上索引更新,会使得这样的操作比较慢. insert-这是一个insert插入操作.

getmore-这是一个getmore 操作,getmore通常发生在结果集比较大的查询时,第一个query返回了部分结果,后续的结果是通过getmore来获取的。 2、优化

MongoDB 查询优化

如果nscanned(扫描的记录数)远大于nreturned(返回结果的记录数)的话,那么我们就要考虑通过加索引来优化记录定位了。

reslen 如果过大,那么说明我们返回的结果集太大了,这时请查看find函数的第二个参数是否只写上了你需要的属性名。(类似于MySQL中不要总是select *)

对于创建索引的建议是:如果很少读,那么尽量不要添加索引,因为索引越多,写操作会越慢。如果读量很大,那么创建索引还是比较划算的。 MongoDB 更新优化

如果写查询量或者update量过大的话,多加索引是会有好处的。以及~~~~(省略N字,和RDBMS差不多的道理)

Use fast modify operations when possible (and usually with these, an index). See Updates.

Profiler 的效率

Profiling 功能肯定是会影响效率的,但是不太严重,原因是他使用的是system.profile 来记录,而system.profile 是一个capped collection 这种collection 在操作上有一些限制和特点,但是效率更高。 优化建议:

如果 nscanned 远大于 nreturned,那么需要使用索引。 如果 reslen 返回字节非常大,那么考虑只获取所需的字段。

执行 update 操作时同样检查一下 nscanned,并使用索引减少文档扫描数量。 使用 db.eval() 在服务端执行某些统计操作。 减少返回文档数量,使用 skip & limit 分页。

因篇幅问题不能全部显示,请点此查看更多更全内容

Top