Quantcast
Channel: CodeSection,代码区,数据库(综合) - CodeSec
Viewing all articles
Browse latest Browse all 6262

MongoDB学习笔记六―查询下

$
0
0
查询内嵌文档 数据准备
> db.blog.find().pretty()
{
"_id" : ObjectId("585694e4c5b0525a48a441b5"),
"content" : "...",
"comments" : [
{
"comment" : "good post",
"author" : "jim",
"votes" : 15
},
{
"comment" : "i thought it was too short",
"author" : "yyb",
"votes" : 3
},
{
"comment" : "free watches",
"author" : "alice",
"votes" : 3
}
]
}
{
"_id" : ObjectId("585f659898992d5a44085fc0"),
"content" : "query",
"comments" : [
{
"comment" : "good post two",
"author" : "yyb",
"votes" : 10
},
{
"comment" : "i thought it was vary good",
"author" : "mmq",
"votes" : 30
},
{
"comment" : "free watches two",
"author" : "lf",
"votes" : 20
}
]
}
>
方式 1 :查询整个内嵌文档

与普通查询完全相同。但是,如果要查询一个完整的子文档,那么子文档必须精确匹配(顺序以及个数都要一样)。


> db.blog.find({"comments":{"author":"lf","votes":20}}) >
> db.blog.find({"comments":{"comment":"free watches two","author":"lf","votes":20}}).pretty()
{
"_id" : ObjectId("585f659898992d5a44085fc0"),
"content" : "query",
"comments" : [
{
"comment" : "good post two",
"author" : "yyb",
"votes" : 10
},
{
"comment" : "i thought it was vary good",
"author" : "mmq",
"votes" : 30
},
{
"comment" : "free watches two",
"author" : "lf",
"votes" : 20
}
]
}
>
方式 2 :只针对其键 / 值对进行查询
> db.blog.find({"comments.author":"yyb","comments.votes":10}).pretty()
{
"_id" : ObjectId("585f659898992d5a44085fc0"),
"content" : "query",
"comments" : [
{
"comment" : "good post two",
"author" : "yyb",
"votes" : 10
},
{
"comment" : "i thought it was vary good",
"author" : "mmq",
"votes" : 30
},
{
"comment" : "free watches two",
"author" : "lf",
"votes" : 20
}
]
}

如果想要查找由 yyb 发表的 11 分以上的投票。不能直接使用以下方式


> db.blog.find({"comments":{"author":"yyb","votes":{"$gt":11}}})
>

或者


> db.blog.find({"comments.author":"yyb","comments.votes":{"$gt":11}})//本来没有,但却查出来两条
{ "_id" : ObjectId("585694e4c5b0525a48a441b5"), "content" : "...", "comments" : [ { "comment" : "good post", "author" : "jim", "votes" : 15 }, { "comment" : "i thought it was too short", "author" : "yyb", "votes" : 3 }, { "comment" : "free watches", "author" : "alice", "votes" : 3 } ] }
{ "_id" : ObjectId("585f659898992d5a44085fc0"), "content" : "query", "comments" : [ { "comment" : "good post two", "author" : "yyb", "votes" : 10 }, { "comment" : "i thought it was vary good", "author" : "mmq", "votes" : 30 }, { "comment" : "free watches two", "author" : "lf", "votes" : 20 } ] }
$elemMatch

要正确地指定一组条件,而不必指定每个键 , 就需要使用 $elemMatch 。这种模糊的命名条件句能用来在查询条件中部分指定匹配数组中的单个内嵌文档。

$elemMatch将限定条件进行分组,仅当需要对一个内嵌文档的多个键操作时才会用到。


> db.blog.find({"comments":{"$elemMatch":{"author":"yyb","votes":{"$gt":11}}}})//无匹配结果 > db.blog.find({"comments":{"$elemMatch":{"author":"yyb","votes":{"$gte":10}}}}).pretty()
{
"_id" : ObjectId("585f659898992d5a44085fc0"),
"content" : "query",
"comments" : [
{
"comment" : "good post two",
"author" : "yyb",
"votes" : 10
},
{
"comment" : "i thought it was vary good",
"author" : "mmq",
"votes" : 30
},
{
"comment" : "free watches two",
"author" : "lf",
"votes" : 20
}
]
}
>
$where

用它可以在查询中执行任意的 js 。这样就能在查询中做任何事情,为安全起见,应该严格限制或消除 $where 语句的使用。应该禁止终端用户使用任意的 $where 语句。

如果函数返回 true, 文档就作为结果集的一部分返回;如果为 false ,就不返回。

使用 $where 在速度上要比常规查询慢很多。每个文档都要从 BSON 转换成 js 对象,然后通过 $where 表达式来运行。而且不能使用索引。实在不得已,最好先使用常规查询(或索引)进行过滤,然后使用 $where 语句,这样组合使用可以降低性能损失。

$where 语句最常见的应用就是比较文档中的两个键的值是否相等。比如:


> db.foo.insert({"apple":1,"banana":6,"pach":3})
WriteResult({ "nInserted" : 1 })
> db.foo.insert({"apple":8,"banana":4,"pach":4})
WriteResult({ "nInserted" : 1 })
> db.foo.find({"$where":function(){
... for(var cur in this){
... for(var other in this){
... if(cur!=other && this[cur]==this[other]){
... return true;
... }
... }
... }
... return false;
... }});
{ "_id" : ObjectId("585f768398992d5a44085fc2"), "apple" : 8, "banana" : 4, "pach" : 4 }
>
游标

数据库使用游标返回 find 的执行结果。客户端对游标的实现通常能够对最终结果进行有效地控制。可以限制结果的数量,略过部分结果,根据任意键按任意顺序的组合对结果进行各种排序,或者执行其他一些强大的操作。


> for(i=0;i<100;i++){
... db.coll.insert({x:i});
... }
WriteResult({ "nInserted" : 1 })
> var cursor=db.coll.find()
> while(cursor.hasNext()){
... obj=cursor.next();
... print(obj.x+"============"+obj._id);
... }
0============585f7c3a98992d5a44085fc3 1============585f7c3a98992d5a44085fc4 2============585f7c3a98992d5a44085fc5 3============585f7c3a98992d5a44085fc6
......

cursor.hasNext() 检查是否有后续结果存在,然后用 cursor.next() 获取它。

游标类还实现了 js 的迭代接口,所以可以在 forEach 循环中使用:


> var coll=db.coll.find({"x":{"$lte":3}})
> coll.forEach(function(row){
... print(row._id+"========="+row.x);
... })
585f7d0298992d5a44086027=========0
585f7d0298992d5a44086028=========1
585f7d0298992d5a44086029=========2
585f7d0298992d5a4408602a=========3
>

调用 find 时, shell 并不立即查询数据库,而是等待真正开始获得结果时才发送查询,这样在执行之前可以给查询附加额外的选项。

几乎游标对象的每个方法都返回游标本身,这样就可以按照任意顺序组成方法链。例如,下面几种表达是等价的:


> var cursor=db.coll.find().sort({"x":-1}).skip(10).limit(1)//实现分页的方式:先倒序,跳过10条,

Viewing all articles
Browse latest Browse all 6262

Trending Articles