首页 > 代码库 > 第一部分 基础篇 第四章 MongoDB查询
第一部分 基础篇 第四章 MongoDB查询
声明:该文章主要来自《MongoDB实战》一书内容,主要想通过该书学习MongoDB的相应知识,加深理解,故写在自己的博文当中,作为记录,在最后的章节中,会有一个自己集合MongoDB数据库应用的JavaEE的web应用。
1、查询记录
1.1、普通查询
在没有深入查询之前,我们先看看怎么从一个查询中返回一个游标对象,可以简单的通过find()来查询,它返回一个任意结构的集合,如果实现特定的查询在稍后讲解。
实现上面同样的查询,然后通过while来输出:
> var cursor = db.xuz.find();
> while(cursor.hasNext()) printjson(cursor.next());
{ "_id" : ObjectId("54a8a4ff2db3e1b27d0e5203"), "name" : "mongo" }
{ "_id" : ObjectId("54a8a5042db3e1b27d0e5204"), "x" : 4 }
{ "_id" : ObjectId("54a8a5a427681683ca2c2466"), "x" : 5, "j" : 1 }
{ "_id" : ObjectId("54a8a5a427681683ca2c2467"), "x" : 5, "j" : 2 }
{ "_id" : ObjectId("54a8a5a427681683ca2c2468"), "x" : 5, "j" : 3 }
{ "_id" : ObjectId("54a8a5a427681683ca2c2469"), "x" : 5, "j" : 4 }
{ "_id" : ObjectId("54a8a5a427681683ca2c246a"), "x" : 5, "j" : 5 }
{ "_id" : ObjectId("54a8a5a427681683ca2c246b"), "x" : 5, "j" : 6 }
{ "_id" : ObjectId("54a8a5a427681683ca2c246c"), "x" : 5, "j" : 7 }
{ "_id" : ObjectId("54a8a5a427681683ca2c246d"), "x" : 5, "j" : 8 }
{ "_id" : ObjectId("54a8a5a427681683ca2c246e"), "x" : 5, "j" : 9 }
{ "_id" : ObjectId("54a8a5a427681683ca2c246f"), "x" : 5, "j" : 10 }
>
上面的例子显示了游标风格的迭代输出,.hasNext()函数告诉我们是否还有数据,如果有则可以调用next()函数。
当我们使用的是JavaScript shell,可以用到JS的特性,forEach就可以输出游标了,下面的例子就是使用forEach()来循环输出:forEach()必须定义一个函数供每个游标元素调用。
> db.xuz.find().forEach(printjson)
{ "_id" : ObjectId("54a8a4ff2db3e1b27d0e5203"), "name" : "mongo" }
{ "_id" : ObjectId("54a8a5042db3e1b27d0e5204"), "x" : 4 }
{ "_id" : ObjectId("54a8a5a427681683ca2c2466"), "x" : 5, "j" : 1 }
{ "_id" : ObjectId("54a8a5a427681683ca2c2467"), "x" : 5, "j" : 2 }
{ "_id" : ObjectId("54a8a5a427681683ca2c2468"), "x" : 5, "j" : 3 }
{ "_id" : ObjectId("54a8a5a427681683ca2c2469"), "x" : 5, "j" : 4 }
{ "_id" : ObjectId("54a8a5a427681683ca2c246a"), "x" : 5, "j" : 5 }
{ "_id" : ObjectId("54a8a5a427681683ca2c246b"), "x" : 5, "j" : 6 }
{ "_id" : ObjectId("54a8a5a427681683ca2c246c"), "x" : 5, "j" : 7 }
{ "_id" : ObjectId("54a8a5a427681683ca2c246d"), "x" : 5, "j" : 8 }
{ "_id" : ObjectId("54a8a5a427681683ca2c246e"), "x" : 5, "j" : 9 }
{ "_id" : ObjectId("54a8a5a427681683ca2c246f"), "x" : 5, "j" : 10 }
在MongoDB shell里,我们也可以把游标当做数组来使用:
> var cursor = db.xuz.find();
> printjson(cursor[4]);
{ "_id" : ObjectId("54a8a5a427681683ca2c2468"), "x" : 5, "j" : 3 }
使用游标时候请注意占用内存的问题,特别是很大的游标对象,有可能会内存溢出,所以以你更改用迭代的方式来输出,下面的实例则是把游标转换成真实的数组类型:
> var arr = db.xuz.find().toArray();
> arr[4];
{ "_id" : ObjectId("54a8a5a427681683ca2c2468"), "x" : 5, "j" : 3 }
请注意这些特性只是在Mongo Shell里使用,而不是所有的其他应用程序驱动都支持,MongoDB游标对象不是没有快照,如果有其他用户在集合里第一次或者最后一次调用next(),你可能得不到游标里的数据,所以要明确的锁定你要查询的游标。
1.2、条件查询
到这里我们已经知道怎么从游标里实现一个查询并返回数据对象,下面就来看看怎么根据指定的条件来查询。
下面的实例就是说明如何执行一个类似SQL的查询,并演示了怎么在MongoDB里实现,这是在MongoDB shell里查询,当然你也可以用其他的应用程序驱动或者语言来实现:
SQL:select * from xuz where name="mongo";
MongoDB:
> db.xuz.find({name:"mongo"}).forEach(printjson);
{ "_id" : ObjectId("54a8a4ff2db3e1b27d0e5203"), "name" : "mongo" }
SQL:select * from xuz where x=4
MongoDB:
> db.xuz.find({x:4}).forEach(printjson);
{ "_id" : ObjectId("54a8a5042db3e1b27d0e5204"), "x" : 4 }
查询条件是{a:A,b:B,....}类似于where a==A and b==B and ....
上面显示的是所有的元素,当然我们也可以返回特定的元素,类似于返回表里某个字段的值,只需要在find({x:4})里指定元素的名字。
SQL:select j from xuz where x=4
MongoDB:
> db.xuz.find({x:5},{j:true}).forEach(printjson);
{ "_id" : ObjectId("54a8a5a427681683ca2c2466"), "j" : 1 }
{ "_id" : ObjectId("54a8a5a427681683ca2c2467"), "j" : 2 }
{ "_id" : ObjectId("54a8a5a427681683ca2c2468"), "j" : 3 }
{ "_id" : ObjectId("54a8a5a427681683ca2c2469"), "j" : 4 }
{ "_id" : ObjectId("54a8a5a427681683ca2c246a"), "j" : 5 }
1.3、findOne()语法
为了方便考虑,MongoDB shell避免游标可能带来的开销,提供一个findOne()函数,这个函数和find()函数一样,不过它返回的是游标里第一条数据,或者返回null,即空数据。
作为一个例子,name="mongo"可以用很多方法来实现,可以用next()来循环游标或者当做数组返回第一个元素。
但是用findOne()方法则更简单和高效:
> printjson(db.xuz.findOne({name:"mongo"}))
{ "_id" : ObjectId("54a8a4ff2db3e1b27d0e5203"), "name" : "mongo" }
1.4、通过limit限制结果集数量
如果需要限制结果集的长度,那么可以调用limit方法
这是强烈推荐解决性能问题的额方法,就是通过限制条数来减少网络传输,比如:
> db.xuz.find().limit(3)
{ "_id" : ObjectId("54a8a4ff2db3e1b27d0e5203"), "name" : "mongo" }
{ "_id" : ObjectId("54a8a5042db3e1b27d0e5204"), "x" : 4 }
{ "_id" : ObjectId("54a8a5a427681683ca2c2466"), "x" : 5, "j" : 1 }
> db.xuz.find().count();
63
通过上面可以知道,xuz集合中总共有63条数据,然后设定limit的值之后只查询出3条数据,limit也是分页查询常用到。
2、修改记录
将name是mongo的记录的name修改为mongo_new。
> db.xuz.update({name:"mongo"},{$set:{name:"mongo_new"}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.xuz.find();
{ "_id" : ObjectId("54a8a4ff2db3e1b27d0e5203"), "name" : "mongo_new" }
3、删除记录
将用户name是mongo_new的记录从集合xuz中删除。
> db.xuz.remove({name:"mongo_new"});
WriteResult({ "nRemoved" : 1 })
> db.xuz.find();
{ "_id" : ObjectId("54a8a5042db3e1b27d0e5204"), "x" : 4 }
{ "_id" : ObjectId("54a8a5a427681683ca2c2466"), "x" : 5, "j" : 1 }
{ "_id" : ObjectId("54a8a5a427681683ca2c2467"), "x" : 5, "j" : 2 }
{ "_id" : ObjectId("54a8a5a427681683ca2c2468"), "x" : 5, "j" : 3 }
{ "_id" : ObjectId("54a8a5a427681683ca2c2469"), "x" : 5, "j" : 4 }
{ "_id" : ObjectId("54a8a5a427681683ca2c246a"), "x" : 5, "j" : 5 }
{ "_id" : ObjectId("54a8a5a427681683ca2c246b"), "x" : 5, "j" : 6 }
{ "_id" : ObjectId("54a8a5a427681683ca2c246c"), "x" : 5, "j" : 7 }
{ "_id" : ObjectId("54a8a5a427681683ca2c246d"), "x" : 5, "j" : 8 }
{ "_id" : ObjectId("54a8a5a427681683ca2c246e"), "x" : 5, "j" : 9 }
{ "_id" : ObjectId("54a8a5a427681683ca2c246f"), "x" : 5, "j" : 10 }
经验证却是没有name为mongo_new的记录了。
4、常用工具集
MongoDB在bin目录下提供了一系列有用的工具,这些工具提供了MongoDB在运维管理上的方便。
- bsondump:将bson格式的文件转存为json格式的数据。
- mongo:客户端命令行工具,其实也是一个JS解释器,支持JS语法
- mongod:数据库服务端,每个实例启动一个进程,可以fork为后台运行。
- mongodump/mongorestore:数据备份和恢复工具。
- mongoexport/mongoimport:数据导出和导入工具。
- mongofile:GridFS管理工具,可实现二进制文件的存取。
- mongos:分片路由,如果使用了sharding功能,则应用程序连接的是mongos而不是mongod。
- mongostat:实时性能监控工具。
- mongotop:提供每个集合的水平的统计数据。
第一部分 基础篇 第四章 MongoDB查询