MongoDB查询(下)
MongoDB查询(下)
相关链接:
MongoDB查询(上)
http://www.zzzyk.com/database/201207/144487.html
1.查询内嵌文档
有两种方法查询内嵌文档:查询整个文档,或者只针对其键值对进行查询
查询整个内嵌文档与普通查询相同
如:
db.users.insert(
{
"name":
{
"first":"refactor",
"last":"refactor2"
},
"age":24
}
) www.zzzyk.com
查找姓名为refactor的文档
db.users.find({"name":{"first":"refactor","last":"refactor2"}})
但是
db.users.find({"name":{"first":"refactor"}})这样不能查询出文档.
所以最好通过内嵌文档的特定的键值来进行查找.这样即便数据模式改变,也不会导致查询失效.
如:
db.users.find({"name.first":"refactor","name.last":"refactor2"})
db.users.find({"name.first":"refactor"})//这个也可以查出文档.
查询文档可以包含点,来表示"深入内嵌文档内部"的意思.点表示法也是待插入的文档不能包含"."的原因.
当文档结构变得更加复杂后,内嵌文档的匹配需要技巧
如:
db.blog.insert(
{
"title":"refactor's blog",
"Content":"refactor's blog test",
"comments":
[
{
"author":"refactor",
"score":3,
"commnent":"nice"
},
{
"author":"refactor2",
"score":6,
"commnent":"good"
} www.zzzyk.com
]
}
)
要查询键author为refactor,score大于等于5的评论
不能使用
db.blog.find(
{"comments":{"author":"refactor","score":{"$gte":5}}}
)来查询.
内嵌文档匹配要求整个内嵌文档完全匹配,而这不会匹配"comments"键.使用
db.blog.find(
{"comments.author":"refactor","comments.score":{"$gte":5}}
)也不会达到目的,因为符合author条件的评论和符合score条件的评论可能不是同一条评论.也就是说,
会返回刚才显示的那个文档.因为"author":"refactor"在第一条评论中匹配了,"score":6在第二条评论中匹配了.
要正确指定一组条件,而不用指定每个键,要使用"$elemMatch".这种模糊的命名条件能用来部分指定匹配数组中
的单个内嵌文档的限定条件.正确写法应该是:
db.blog.find(
{
"comments":
{
"$elemMatch":
{
"author":"refactor",
"score":{"$gte":5}
}
}
}
)
"$elemMatch"将限定条件进行分组,仅当需要对一个内嵌文档的多个键操作时才会用到.
2."$where"查询
"$where"可以执行任意javascript作为查询的一部分.这使得查询能做(几乎)任何事情.
最典型的应用就是比较文档中的两个键的值是否相等.
如: www.zzzyk.com
db.blog.insert({"title":"refactor","content":"refactor"})
db.blog.insert({"title":"refactor1","content":"refactor content"})
第一个文档title键和content键的值相同.要返回该文档.
db.blog.find(
{
"$where":function()
{
for(var current in this)
{
for(var other in this)
{
if(current!=other&&this[current]==this[other])
{
return true;
}
}
}
return false;
}
}
)
如果函数返回true,文档就作为结果的一部分被返回.
上面是用一个函数,也可以用一个字符串指定"$where"查询.下面两种方式是等价的:
db.blog.find({"$where":"this.x+this.y==10"})
db.blog.find({"$where":"function(){return this.x+this.y==10;}"})
不是非常必要时,应避免"$where"查询.它在速度上要比常规查询慢的多.每个文档都要从BSON转换成
javascript对象,然后通过"$where"的表达式来运行.它还不能利用索引.
将常规查询作为前置过滤,与"$where"组合使用才能不牺牲性能,如果有可能的话,用索引根据非"$where"
子句进行过滤,"$where"只用于对结果进行调优.
3.游标
数据库使用游标来返回find的执行结果.客户端对游标的实现通常能够对最终结果进行有效的控制.可以限制
结果的数量,略过部分结果,根据任意方向任意键的组合对结果进行各种排序,或者是执行其他一些强大的操作.
要想在shell中创建一个游标,首先要对集合填充一些文档,然后对齐执行查询,并将结果分配给一个局部变量.
如:
for(i=0;i<100;i++){db.refactor.insert({"refactorValue":i});}
var cursor=db.refactor.find();
cursor.forEach(
function(x)
{
print(x.refactorValue);
}
) www.zzzyk.com
这样做的好处是一次可以查看一条结果.如果将结果放在全局变量或者就没有放在变量中,MongoDB shell
会自动迭代,自动显示最开始的若干文档.
var cursor=db.refactor.find();当调用find的时候,shell并不立即查询数据库,而是等待真正开始要求获得结果
的时候才发送查询,这样执行之前可以给查询附加额外的选项.几乎所有游标对象的方法都返回游标本身,这样
可以按照任意顺序组成方法链.下面几种方式是等价的:
var cursor=db.refactor.find().sort({"refactorValue":1}).limit(1).skip(10);
var cursor=db.refactor.find().limit(1).sort({"refactorValue":1}).skip(10);
var cursor=db.refactor.find().skip(10).sort({"refactorValue":1}).limit(1);
此时,查询还没有执行,所有这些函数都只是构造查询,执行如下操作:
cursor.hasNext()
这时,查询会发往服务器.shell立即获取前100个结果或者前4M数据(两者之中的较小者).等到客户端用光了第一组结果,shell会再一次连接数据库,并请求结果,这个过程一直会持续到游标好近或者结果全部返回.
4.limit,skip,sort
最常用的查询选项是限制返回结果的数量,忽略一定数量的结果并排序,所有这些选项一定要在查询被派发到服务器之前添加
限制结果数量,在find后使用limit函数
如:返回5个结果:
db.refactor.find().limit(5)
如果匹配的结果不到5个,则返回匹配数量的结果.
skip和limit类似.
db.refactor.skip(5)
略过前5个,然后返回余下的文档.如果集合里匹配的小于5个,这不返回任何文档.
- 更多mongodb疑问解答:
- 【急】MongoDB写入错误~~~~
- Mongodb NOSql 数据库问题,是否可以插入带接口的类
- java操作mongodb
- Spring data MongoDB 更新整个内嵌文档时报错???????
- node.js连接mongodb更新
- MongoDB Java驱动 WriteConcern.SAFE非常浪费资源
- 求科普,hibernate怎样操作mongodb?
- 问一下mongodb怎么用hibernate整合
- mongodb查询的数据过多
- 使用JAVA创建MongoDB的问题
- Mongodb事务管理问题?
- mongodb利用java进行模糊查询
- spring 抽象类 注入值为空(spring3+mongodb+morphia)
- 【急】MongoDB写入错误~~~~
- Mongodb NOSql 数据库问题,是否可以插入带接口的类