MongoDB入门必读(概念与实战并重)

MongoDB入门必读(概念与实战并重)

一、概述

  MongoDB是一个基于分布式文件存储的数据库开源项目。由C++语言编写。旨在为WEB应用提供可护展的高性能数据存储解决方案。

  MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似json的bjson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

Mongo主要解决的是海量数据的访问效率问题,根据官方的文档,当数据量达到50GB以上的时候,Mongo的数据库访问速度是MySQL的10倍以上。Mongo的并发读写效率不是特别出色,根据官方提供的性能测试表明,大约每秒可以处理0.5万-1.5次读写请求。

因为Mongo主要是支持海量数据存储的,所以Mongo还自带了一个出色的分布式文件系统GridFS,可以支持海量的数据存储,但我也看到有些评论认为GridFS性能不佳,有待验证。

最后由于Mongo可以支持复杂的数据结构
而且带有强大的数据查询功能,因此非常受到欢迎,很多项目都考虑用MongoDB来替代MySQL来实现不是特别复杂的Web应用,比方说why we
migrated from MySQL to
MongoDB就是一个真实的从MySQL迁移到MongoDB的案例,由于数据量实在太大,所以迁移到了Mongo上面,数据查询的速度得到了非常显著
的提升。

MongoDB也有一个ruby的项目MongoMapper,是模仿Merb的DataMapper编写的MongoDB的接口,使用起来非常简单,几乎和DataMapper一模一样,功能非常强大易用。

  总结起来,monggDB的特点是高性能、易部署、易使用,存储数据非常方便。主要功能特性有:

  *面向集合存储,易存储对象类型的数据。
*模式*。
*支持动态查询。
*支持完全索引,包含内部对象。
*支持查询。
*支持复制和故障恢复。
*使用高效的二进制数据存储,包括大型对象(如视频等)。
*自动处理碎片,以支持云计算层次的扩展性
*支持RUBY,PYTHON,JAVA,C++,PHP等多种语言。
*文件存储格式为BSON(一种JSON的扩展)
*可通过网络访问

  所谓“面向集合”(Collenction-Orented),意思是数据被分组存储在数据集中,被称为一个集合(Collenction)。
每个集合在数据库中都有一个唯一的标识名,并且可以包含无限数目的文档。集合的概念类似关系型数据库(RDBMS)里的表(table),不同的是它不需
要定义任何模式(schema)。
模式*(schema-free),意味着对于存储在mongodb数据库中的文件,我们不需要知道它的任何结构定义。如果需要的话,你完全可以把不同结构的文件存储在同一个数据库里。
存储在集合中的文档,被存储为键-值对的形式。键用于唯一标识一个文档,为字符串类型,而值则可以是各中复杂的文件类型。我们称这种存储形式为BSON(Binary Serialized dOcument Format)。

  推荐阅读:

  Ubuntu 13.04下安装MongoDB2.4.3

  如何在MongoDB中建立新数据库和集合

MongoDB的优点

高性能,速度非常快(如果你的内存足够的话)

没有固定的表结构,不用为了修改表结构而进行数据迁移

查询语言简单,容易上手

使用Sharding实现水平扩展

部署方便

使用MongoDB,你得记住以下几点:

MongoDB 假设你有大磁盘空间

MongoDB 假设你的内存也足够大于放下你的热数据

MongoDB 假设你是部署在64位系统上的(32位有2G的限制,试用还可以)

MongoDB 假设你的系统是little-endian的

MongoDB 假设你有多台机器(并不专注于单机可靠性)

MongoDB 假设你希望用安全换性能,同时允许你用性能换安全

MongoDB在下面领域不太擅长

不太稳定,特别是auto-sharding目前还有很多问题

不支持SQL,这意味着你很多通过SQL接口的工具不再适用

持久化,MongoDB单机可靠性不太好,宕机可能丢失一段时间的数据

相关文档比较少,新功能都有这个问题

相关人才比较难找,这也是新功能的问题之一

  二、安装

  MongoDB服务端可运行在Linux、Windows或OS X平台,支持32位和64位应用,默认端口为27017。推荐运行在64位平台,因为MongoDB

  在32位模式运行时支持的最大文件尺寸为2GB。MongoDB把数据存储在文件中(默认路径为:/data/db),为提高效率使用内存映射文件进行管理。

  (一)Linux/OS X下:
1 建立数据目录
mkdir -p /data/db
2 下载压缩包
curl -O
3 解压缩文件
tar xzf mongodb-linux-i386-latest.tgz
4 启动服务
bin/mongod run &
5 使用自带客户端连接
/bin/mongo
6 测试
db.foo.save( { a : 1 } )
db.foo.findOne()

  (二)windows下:

  1 建立数据目录c:\data\db
2 下载压缩包,解压文件
3 启动服务
bin\mongod.exe run
4 自带客户端
bin\mongon.exe

  在LINUX和WINDOWS系统下的使用大同小异,不同的地方主要是默认的数据存储目录。LINUX类系统下存放在/data/db下,而WINDOWS

  会存放在C:\data\db下。可以在启动时使用--dbpath参数指定存储目录并启动。如:bin\mongod.exe --dbpath d:\data\mongo

  常用启动参数:
run 直接启动。例:./mongod run
--dbpath 指定特定存储目录启动,若目录不存在则创建。例:./mongod --dbpath /var/data/mongo
--port 指定端口启动。例:./mongod --port 12345

  停止MONGO服务:
方法1:服务端停止,可使用Ctrl+C
方法2:在客户端停止,可先连接客户端
./mongo
并使用命令
db.shutdownerver()
然后退出客户端
exit

  三、mongoDB常用命令

  1、与Mql对照

  MySQL

  MongoDB

  说明

  mysqld

  mongod

  服务器守护进程

  mysql

  mongo

  客户端工具

  mysqldump

  mongodump

  逻辑备份工具

  mysql

  mongorestore

  逻辑恢复工具

  db.repairDatabase()

  修复数据库

  mysqldump

  mongoexport

  数据导出工具

  source

  mongoimport

  数据导入工具

  grant * privileges on *.* to …

  Db.addUser()

  Db.auth()

  新建用户并权限

  show databases

  show dbs

  显示库列表

  Show tables

  Show collections

  显示表列表

  Show slave status

  Rs.status

  查询主从状态

  Create table users(a int, b int)

  db.createCollection("mycoll", {capped:true,

  size:100000}) 另:可隐式创建表。

  创建表

  Create INDEX idxname ON users(name)

  db.users.ensureIndex({name:1})

  创建索引

  Create INDEX idxname ON users(name,ts DESC)

  db.users.ensureIndex({name:1,ts:-1})

  创建索引

  Insert into users values(1, 1)

  db.users.insert({a:1, b:1})

  插入记录

  Select a, b from users

  db.users.find({},{a:1, b:1})

  查询表

  Select * from users

  db.users.find()

  查询表

  Select * from users where age=33

  db.users.find({age:33})

  条件查询

  Select a, b from users where age=33

  db.users.find({age:33},{a:1, b:1})

  条件查询

  select * from users where age<33

  db.users.find({'age':{$lt:33}})

  条件查询

  select * from users where age>33 and age<=40

  db.users.find({'age':{$gt:33,$lte:40}})

  条件查询

  

  select * from users where a=1 and b='q'

  db.users.find({a:1,b:'q'})

  条件查询

  select * from users where a=1 or b=2

  db.users.find( { $or : [ { a : 1 } , { b : 2 } ] } )

  条件查询

  select * from users limit 1

  db.users.findOne()

  条件查询

  select * from users where name like "%Joe%"

  db.users.find({name:/Joe/})

  模糊查询

  select * from users where name like "Joe%"

  db.users.find({name:/^Joe/})

  模糊查询

  select count(1) from users

  Dunt()

  获取表记录数

  select count(1) from users where age>30

  db.users.find({age: {'$gt': 30}}unt()

  获取表记录数

  select DISTINCT last_name from users

  db.users.distinct('last_name')

  去掉重复值

  select * from users ORDER BY name

  db.users.find().sort({name:-1})

  排序

  select * from users ORDER BY name DESC

  db.users.find().sort({name:-1})

  排序

  EXPLAIN select * from users where z=3

  db.users.find({z:3}).explain()

  获取存储路径

  update users set a=1 where b='q'

  db.users.update({b:'q'}, {$set:{a:1}}, false, true)

  更新记录

  update users set a=a+2 where b='q'

  db.users.update({b:'q'}, {$inc:{a:2}}, false, true)

  更新记录

  delete from users where z="abc"

  db.users.remove({z:'abc'})

  删除记录

  db. users.remove()

  删除所有的记录

  drop database IF EXISTS test;

  use test

  db.dropDatabase()

  删除数据库

  drop table IF EXISTS test;

  db.mytable.drop()

  删除表/collection

  db.addUser(‘test’, ’test’)

  添加用户

  readOnly-->false

  db.addUser(‘test’, ’test’, true)

  添加用户

  readOnly-->true

  db.addUser("test","test222")

  更改密码

  db.system.users.remove({user:"test"})

  或者db.removeUser('test')

  删除用户

  

  use admin

  超级用户

  db.auth(‘test’, ‘test’)

  用户授权

  db.system.users.find()

  查看用户列表

  show users

  查看所有用户

  db.printCollectionStats()

  查看各collection的状态

  db.printReplicationInfo()

  查看主从复制状态

  show profile

  查看profiling

  pyDatabase('mail_addr','mail_addr_tmp')

  拷贝数据库

  db.users.dataSize()

  查看collection数据的大小

  db. users.totalIndexSize()

  查询索引的大小

  2、shell数据操作实战

插入数据到集合

  下面我们来建立一个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")}>

  有几点需要注意下 :

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

在例子其实可以存储任何结构的数据, 当然在实际应用我们存储的还是相同元素的集合. 这个特性其实可以在应用里很灵活, 你不需要类似alter table 来修改你的数据结构

每次插入数据时候对象都会有一个ID, 名字叫 _id.

当你运行不同的例子, 你的对象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"}).forEach(function(x) {
print(tojson(x));});{"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 来查询具体的说明.

  这篇写得常用命令也不错

  四、与java结合

  使用JAVA语言操作MONGODB非常简单,只要将驱动文件加入到CLASSPATH中就可以使用。

  MongoDB入门必读(概念与实战并重)

  junit-4.11和hamcrest-core-1.3是junit4依赖包

  mongo-java-driver-2.9.3为mongodb的java驱动包

  实战:

  import com.mongodb.Mongo;
import com.mongodb.DBCollection;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.DBCursor;
import com.mongodb.MongoAdmin;

  1、获得连接

  Mongo db = new Mongo("mydb");
Mongo db = new Mongo("localhost", "mydb");
Mongo db = new Mongo("localhost", 27017, "mydb");

  查看mongoDB数据库列表
Mongo m = new Mongo();
for (String s : m.getDatabaseNames()) {
System.out.println(s);
}

  删除一个数据库
Mongo m = new Mongo();
m.dropDatabase("myDatabaseName");

  2 安全验证(非必选)
MongoDB服务可以在安全模式运行,此时任何客户端要连接数据库时需使用用户名和密码。在JAVA中可使用如下方法连接:

  boolean auth = db.authenticate(userName, password);

  如果用户名密码验证通过,返回值为true,否则为false

  3 获取集合列表
每个数据库都存在零个或多个集合,需要时你可以获得他们的列表:

  Set<String> colls = db.getCollectionNames();
for(String s : colls){
System.out.println(s);
}

  4 获得一个集合
要获得某个特定集合,你可以指定集合的名字,并使用getCollection()方法:

  DBCollection coll = db.getCollection("testCollection");

  当你获取了这个集合对象,你就可以对数据进行增删查改之类的操作。

  查看一个集合的索引

  List<DBObject> list = coll.getIndexInfo();
for (DBObject o : list) {
System.out.println(o);
}

  5 插入文档

  默认ID
当保存的对象没有设置ID时,mongoDB会默认给该条记录设置一个ID("_id")。
当然你也可以设置自己指定的ID,如:(在mongoDB中执行用db.users.save({_id:1,name:'bruce'});)

  当你获得了一个集合对象,你就可以把文档插入到这个对象中。例如,存在一个JSON式的小文档:
{
"name" : "MongoDB",
"type" : "database",
"count" : 1,
"info" : {
x : 203,
y : 102
}
}
请注意,这个文档包含一个内部文档。我们可以使用BasicDBObject类来创建这个文档,并且使用insert()方法方便地将它插入到集

  合中。

  BasicDBObject doc = new BasicDBObject();
doc.put("name", "MongoDB");
doc.put("type", "database");
doc.put("count", 1);

  BasicDBObject info = new BasicDBObject();
info.put("x", 203);
info.put("y", 102);

  doc.put("info", info);

  coll.insert(doc);

  批量插入
List datas = new ArrayList();
for (int i=0; i < 100; i++) {
BasicDBObject bo = new BasicDBObject();
bo.put("name", "bruce");
bo.append("age", i);
datas.add(bo);
}
coll.insert(datas);

  6 使用findOne()查找集合中第一个文档
要查找我们上一步插入的那个文档,可以简单地使用findOne()操作来获取集合中第一个文档。这个方法返回一个单一文档(这是相对于使用DBCursor的find()操作的返回),这对于只有一个文档或我们刚插入第一个文档时很有用,因为此时并不需要使用光标。

  DBObject myDoc = coll.findOne();
System.out.println(myDoc);

  返回类似:
{
"_id" : "ac907a1f5b9d5e4a233ed300" ,
"name" : "MongoDB" ,
"type" : 1 ,
"info" : {
"x" : 203 ,
"y" : 102} ,
"_ns" : "testCollection"
}

  注意_id和_ns元素是由MongoDB自动加入你的文档。记住:MongoDB内部存储使用的元素名是以“_”做为开始。

  7 加入多种文档
为了做更多有趣的查询试验,让我们向集合中加入多种文档类型,象:
{
"i" : value
}
可以通过循环来实现

  for(int i = 0; i < 100; i++){
coll.insert(new BasicDBObject().append("i", i));
}

  注意我们可以在一个集合中插入不同类型的文档,这就是我们所说的“模式*”(schema-free)。

  8 统计文档数量
使用getCount()方法

  System.out.println(coll.getCount());

  9 使用光标(cursor)来获取全部文档
为了获取集合中的所有文档,我们可以使用find()方法。这个方法返回一上DBCursor对象,来允许我们将符合查询条件的文档迭代

  出来。

  DBCursor cur = coll.find();
while(cur.hasNext()){
System.out.println(cur.next());
}

  10 在查询中获取单一文档
我们可以创建一个查询,并传递给find()方法来获取集合中所有文档的一个子集。例如,我们想要查询域名为"i",并且值为71的文档:

  BasicDBObject query = new BasicDBObject();
query.put("i", 71);
cur = coll.find(query);
while(cur.hasNext()){
System.out.println(cur.next());
}

  类转换
当把一个类对象存到mongoDB后,从mongoDB取出来时使用setObjectClass()将其转换回原来的类。
public class Tweet implements DBObject {
/* ... */
}
Tweet myTweet = new Tweet();
myTweet.put("user", "bruce");
myTweet.put("message", "fun");
myTweet.put("date", new Date());
collection.insert(myTweet);
//转换
collection.setObjectClass(Tweet);
Tweet myTweet = (Tweet)collection.findOne();

  11 使用条件查询获取集合

  比较符
"$gt": 大于
"$gte":大于等于
"$lt": 小于
"$lte":小于等于
"$in": 包含

  例如,我们想要查询所有i>50的文档:

  BasicDBObject query = new BasicDBObject();
query.put("i", new BasicDBObject("$gt", 50));
cur = coll.find(query);
while(cur.hasNext()){
System.out.println(cur.next());
}

  当然,我们也可以做20 < i <= 30的查询

  BasicDBObject query = new BasicDBObject();
query.put("i", new BasicDBObject("$gt", 20).append("$lte", 30));
cur = coll.find(query);
while(cur.hasNext()){
System.out.println(cur.next());

  }

  正则表达式
查询所有名字匹配 /joh?n/i 的记录
Pattern pattern = pile("joh?n", CASE_INSENSITIVE);
BasicDBObject query = new BasicDBObject("name", pattern);
DBCursor cursor = coll.find(query);

  12 创建索引
MongoDB支持索引,而且很容易在集合上增加索引。要创建索引,只需要指定要加索引的属性,并且指定升序(1)或降序即可(-1)。

  coll.createIndex(new BasicDBObject("i", 1));

  13 获取索引列表

  List<DBObject> list = coll.getIndexInfo();
for(DBObject o : list){
System.out.println(o);
}

  14 MongoDB管理函数
管理函数在com.mongodb.MongoAdmin类中定义。
例A:获取数据库列表
MongoAdmin admin = new MongoAdmin();
for(String s : admin.getDatabaseNames()){
System.out.println(s);
}

  例B:获取数据库对象
Mongo m = admin.getDB("mydb");

  例C:删除数据库
admin.dropDatabase("mydb");

  15 用DBObject存储JAVA对象
MongoDB for JAVA驱动中提供了用于向数据库中存储普通对象的接口DBObject
例如,存在一个需要存储的对象类Tweet
public class Tweet implements DBObject{
/*...*/
}
可以使用如下代码:

  Tweet myTweet = new Tweet();
myTweet.put("user", userId);
myTweet.put("message", message);
myTweet.put("date", new Date());

  collection.insert(myTweet);

  当一个文档从MongoDB中取出时,它会自动把文档转换成DBObject接口类型,要将它实例化为你的对象,需使用

  DBCollection.setObjectClass()。
collection.setObjectClass(Tweet);
Tweet myTweet = (Tweet)collection.findOne();

  16 JAVA驱动的并发性
JAVA的MongoDB驱动是线程安全的。如果你将它用在WEB服务中,可以创建它的一个单例,并在所有请求中使用它。

  然而,如果你需要在一个会话(例如HTTP请求)中保证事务一致性,也许你会希望在这个会话中对驱动使用同一个端口。这仅仅在

  请求量非常大的环境中,例如你经常会读取刚写入的数据。
为了这一点,你需要使用如下代码:
Mongo m;
m.restartStart();

  // code.........

  m.requestDone();

  源码下载地址

  免费下载地址在

  用户名与密码都是

  具体下载目录在 /2013年资料/7月/9日/MongoDB入门必读(概念与实战并重)

上一篇:POJ - 1830:开关问题 (开关问题-高斯消元-*元)


下一篇:解决Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/Student_recruit]]