获取数据库
下载数据库, 解包, 运行mongod:
连接数据库
现在我们通过数据库的shell来实际操作一下。(注意:任何编程语言都可以通过合适的驱动进行类似的操作.只不过shell的方式更方便交互操作。)
运行MongoDB JavaScript shell:
(默认情况下shell将连接本机(localhost)的数据库)你会看到:
MongoDB shell version: 0.9.8
url: test
connecting to: test
type "help" for help
>
"connecting to:" 表明shell连接的数据名。要切换数据库:
输入 help 可以看到一个简单的命令列表。
|
给有其他数据库经验的开发者的提示
在下面的例子中你可能会注意到,我们没有创建数据库和集。MongoDB并不用那么做。一旦你插入内容,MongoDB会建立对应的集和数据库。要是查询了不存在的集,Mongo就将其视为空的集。 |
向集中插入数据
我们建立一个测试用的集,然后插入一些数据。我们将会新建两个对象 j 和 t , 然后将其存放在 things 集中。
下面的例子中, '>' 表示shell命令提示符
> j = { name: "mongo"};
{"name" : "mongo"}
> t = { x : 3 };
{ "x" : 3 }
> db.things.save(j);
> db.things.save(t);
> db.things.find();
in cursor for : DBQuery: example.things ->
{"name" : "mongo" , "_id" : "497cf60751712cf7758fbdbb"}
{"x" : 3 , "_id" : "497cf61651712cf7758fbdbc"}
>
注意事项:
- 我们并没有预先定义集。数据库会在第一次插入操作时自动创建集。
- 我们存储的文档可以拥有任意不同的结构。事实上在本例中,文档之间根本没有共同的数据元素。在实际应用中文档通常都已相同的结构保存在集里面。这种灵活意味着迁移或者扩充都非常容易。几乎不需要写脚本来执行诸如“alter table”之类的操作。
- 一旦被插入数据库,对象就被分配一个ID(要是还没有的话)存储在 _id 域中
- 你运行上面的例子时,你的ObjectID的值会有所不同。
下面再往集里面添加一些记录:
> for( var i = 1; i < 10; i++ ) db.things.save( { x:4, j:i } );
> db.things.find();
in cursor for : DBQuery: example.things ->
{"name" : "mongo" , "_id" : "497cf60751712cf7758fbdbb"}
{"x" : 3 , "_id" : "497cf61651712cf7758fbdbc"}
{"x" : 4 , "j" : 1 , "_id" : "497cf87151712cf7758fbdbd"}
{"x" : 4 , "j" : 2 , "_id" : "497cf87151712cf7758fbdbe"}
{"x" : 4 , "j" : 3 , "_id" : "497cf87151712cf7758fbdbf"}
{"x" : 4 , "j" : 4 , "_id" : "497cf87151712cf7758fbdc0"}
{"x" : 4 , "j" : 5 , "_id" : "497cf87151712cf7758fbdc1"}
{"x" : 4 , "j" : 6 , "_id" : "497cf87151712cf7758fbdc2"}
{"x" : 4 , "j" : 7 , "_id" : "497cf87151712cf7758fbdc3"}
{"x" : 4 , "j" : 8 , "_id" : "497cf87151712cf7758fbdc4"}
has more
注意这里并没有列出所有的文档 - shell 会默认显示10个。先前已经有两个文档在集里面了,所以这里只能看见新插入的前8个文档。
要是想接着看结果,可以用 it 。接着上面的例子往下:
{"x" : 4 , "j" : 7 , "_id" : "497cf87151712cf7758fbdc3"}
{"x" : 4 , "j" : 8 , "_id" : "497cf87151712cf7758fbdc4"}
has more
> it
{"x" : 4 , "j" : 9 , "_id" : "497cf87151712cf7758fbdc5"}
{"x" : 4 , "j" : 10 , "_id" : "497cf87151712cf7758fbdc6"}
通常,find()会返回一个游标对象,但是在上面那个例子中,我们并不确定游标是可移动的。所以shell自动的移动游标,并且把初始化后的结果返回给我们,同时允许我们通过"it"命令继续移动游标。
但是我们仍然可以直接使用游标,在下一部分中将讨论如何这样做。
使用查询访问数据
在我们对查询进行深入讨论之前,我们先来看看如何通过一个游标对象操作查询结果。我们将使用简单的find()查询函数,它会返回一个集(表),并且在随后讨论如何创建一个具体的查询。
在使用mongo shell的时候,为了查看所有集(表)中的数据,我们需要从find()操作中返回一个游标。
然后开始重复相同的查询操作,但是这次我们使用find()返回的游标,并且在while循环中移动游标:
> var cursor = db.things.find();
> while (cursor.hasNext()) { print(tojson(cursor.next())); }
{"name" : "mongo" , "_id" : "497cf60751712cf7758fbdbb"}
{"x" : 3 , "_id" : "497cf61651712cf7758fbdbc"}
{"x" : 4 , "j" : 1 , "_id" : "497cf87151712cf7758fbdbd"}
{"x" : 4 , "j" : 2 , "_id" : "497cf87151712cf7758fbdbe"}
{"x" : 4 , "j" : 3 , "_id" : "497cf87151712cf7758fbdbf"}
{"x" : 4 , "j" : 4 , "_id" : "497cf87151712cf7758fbdc0"}
{"x" : 4 , "j" : 5 , "_id" : "497cf87151712cf7758fbdc1"}
{"x" : 4 , "j" : 6 , "_id" : "497cf87151712cf7758fbdc2"}
{"x" : 4 , "j" : 7 , "_id" : "497cf87151712cf7758fbdc3"}
{"x" : 4 , "j" : 8 , "_id" : "497cf87151712cf7758fbdc4"}
{"x" : 4 , "j" : 9 , "_id" : "497cf87151712cf7758fbdc5"}
>
上述例子展示了一个游标的使用方式,hasNext()函数返回当前的document对象后面是否还有数据,而next()函数则返回一个document对象。同时我们还使用了内嵌的tojson()函数来把document的对象变成JSON数据格式。
这个shell是Javascript的,所以这里还可以享用其语言本身的特性:可以对游标调用 forEach 。还拿上面的例子来说,直接在游标处将循环用 forEach() 换掉了:
> db.things.find().forEach( function(x) { print(tojson(x));});
{"name" : "mongo" , "_id" : "497cf60751712cf7758fbdbb"}
{"x" : 3 , "_id" : "497cf61651712cf7758fbdbc"}
{"x" : 4 , "j" : 1 , "_id" : "497cf87151712cf7758fbdbd"}
{"x" : 4 , "j" : 2 , "_id" : "497cf87151712cf7758fbdbe"}
{"x" : 4 , "j" : 3 , "_id" : "497cf87151712cf7758fbdbf"}
{"x" : 4 , "j" : 4 , "_id" : "497cf87151712cf7758fbdc0"}
{"x" : 4 , "j" : 5 , "_id" : "497cf87151712cf7758fbdc1"}
{"x" : 4 , "j" : 6 , "_id" : "497cf87151712cf7758fbdc2"}
{"x" : 4 , "j" : 7 , "_id" : "497cf87151712cf7758fbdc3"}
{"x" : 4 , "j" : 8 , "_id" : "497cf87151712cf7758fbdc4"}
{"x" : 4 , "j" : 9 , "_id" : "497cf87151712cf7758fbdc5"}
>
在{{forEach()}}里必须定义对游标中的每一个文档的操作函数。
在 mongo shell中,也可以把游标当作数组处理:
> var cursor = db.things.find();
> print (tojson(cursor[4]));
{"x" : 4 , "j" : 3 , "_id" : "497cf87151712cf7758fbdbf"}
当这样使用游标时,注意这会将最大访问数据(上面的例子中的cursor[4])以下的所有数据都同时加载到内存中。这对大结果非常不合适,会导致内存不够用的。返回结果数量很大时,游标应该作为迭代器使用。
In addition to array-style access to a cursor, you may also convert the cursor to a true array:
除了用数组的风格来操作游标,也可以干脆将游标转换程真正的数组:
> var arr = db.things.find().toArray();
> arr[5];
{"x" : 4 , "j" : 4 , "_id" : "497cf87151712cf7758fbdc0"}
请注意这种数组特性是[]特有的,并不是所有的驱动都支持。
MongoDB游标并不做快照。如果你或者别人在你查询时,确切的说从第一次到最后一次调用 {{next}}之间,对数据进行了修改,那么修改可能被返回,也可能不返回。要是想做快照查询的话得使用互斥锁。
h3. 定制查询结果
现在我们知道了如何使用查询返回的游标对象,下面看看如何通过修改查询来定制结果。
通常,可以通过创建一种键值相匹配的”query documents”来实现这个方式。
这些用实例更能说明问题。在下面的例子里,我们将给出SQL查询的例子,并且同时利用MongDB的 [mongo shell|mongo - The Interactive Shell] 实现查询,通过这种方式进行查询对于MongoDB来说是必要的,而且你也会发现其在任何语言环境中的便利性。
{code:title=SELECT * FROM things WHERE name="mongo"}> db.things.find({name:"mongo"}).forEach(function(x) { print(tojson(x));});
{"name" : "mongo" , "_id" : "497cf60751712cf7758fbdbb"}
>
> db.things.find({x:4}).forEach(function(x) { print(tojson(x));});
{"x" : 4 , "j" : 1 , "_id" : "497cf87151712cf7758fbdbd"}
{"x" : 4 , "j" : 2 , "_id" : "497cf87151712cf7758fbdbe"}
{"x" : 4 , "j" : 3 , "_id" : "497cf87151712cf7758fbdbf"}
{"x" : 4 , "j" : 4 , "_id" : "497cf87151712cf7758fbdc0"}
{"x" : 4 , "j" : 5 , "_id" : "497cf87151712cf7758fbdc1"}
{"x" : 4 , "j" : 6 , "_id" : "497cf87151712cf7758fbdc2"}
{"x" : 4 , "j" : 7 , "_id" : "497cf87151712cf7758fbdc3"}
{"x" : 4 , "j" : 8 , "_id" : "497cf87151712cf7758fbdc4"}
{"x" : 4 , "j" : 9 , "_id" : "497cf87151712cf7758fbdc5"}
>
查询表达式本身就是一个document对象,如果是一个类似于{a:A, b:B, …}的document查询对象,则表示”where a=A and b=B and…”,更多关于查询的用法,在 Mongo开发者指南 的 查询与游标 章节中。
MongoDB也允许您返回一个”部分document对象”,也就是返回一个数据库中存储的document的子集。您只要通过使用find()函数的第二个参数就可以做到这一点。
例如,我们在上一个 find({x:4}) 的例子中,加一个函数,就能够只返回j列的数据了:
> db.things.find({x:4}, {j:true}).forEach(function(x) { print(tojson(x));});
{"j" : 1 , "_id" : "497cf87151712cf7758fbdbd"}
{"j" : 2 , "_id" : "497cf87151712cf7758fbdbe"}
{"j" : 3 , "_id" : "497cf87151712cf7758fbdbf"}
{"j" : 4 , "_id" : "497cf87151712cf7758fbdc0"}
{"j" : 5 , "_id" : "497cf87151712cf7758fbdc1"}
{"j" : 6 , "_id" : "497cf87151712cf7758fbdc2"}
{"j" : 7 , "_id" : "497cf87151712cf7758fbdc3"}
{"j" : 8 , "_id" : "497cf87151712cf7758fbdc4"}
{"j" : 9 , "_id" : "497cf87151712cf7758fbdc5"}
>
Note that the "_id" field is always returned.
需要注意的是"_id"列是每次都要被返回的。
findOne() -
为了方便起见,mongo shell(和其他驱动)能避免让你编程处理游标,你只需要通过findOne()函数就能获得一个文档。findOne()和find()使用相同的参数,但是它不返回游标,而是从数据库中返回第一个档,或者没有匹配条目时返回null。
例如,我们可以通过很多种方式检索一个名称为’mongo’的document,包括在游标中调用next()函数(当然,要验证完是否为null之后),或者把游标看做一个数组然后访问数组的[0]下标元素。
无论采用何种方式,findOne()函数还是既方便又高效的:
> var mongo = db.things.findOne({name:"mongo"});
> print(tojson(mongo));
{"name" : "mongo" , "_id" : "497cf60751712cf7758fbdbb"}
>
如果只从数据库返回一个对象,这个方式是更加方便的,并且在数据库和网络传输上有更少的工作需要来做。这种方式等价于find({name:"mongo"}).limit(1)。
使用 limit()
通过 limit() 方法可以指定返回结果的最大数量,这样就能控制查询结果的大小了。
非常推荐使用这种方式,可以提高性能,因为这样减少了数据库的工作量,也减少了网络中的数据流量。举个例子:
> db.things.find().limit(3);
in cursor for : DBQuery: example.things ->
{"name" : "mongo" , "_id" : "497cf60751712cf7758fbdbb"}
{"x" : 3 , "_id" : "497cf61651712cf7758fbdbc"}
{"x" : 4 , "j" : 1 , "_id" : "497cf87151712cf7758fbdbd"}
>
posted on 2010-06-23 15:40
Derek.Guo 阅读(1552)
评论(1) 编辑 收藏 所属分类:
NoSqlDB