Mongodb-查询

find简介

find查询就是返回一个集合中文档的子集,子集的范围从0个文档到整个集合,find的第一个参数决定要返回哪些文档,其形式也是一个文档,说明要执行的细节;空的查询文档默认匹配整个集合。

指定/剔除返回的键

可以通过指定find()或者findOne()方法的第二个参数来约束返回的键值对;

db.Users.find({}, {“name”:1, “email”,1}) 可得到返回值:

{
    "_id" : ObjectId("548546deab91bbcae368ddb2"),
    "name" : "elvis",
    "email" : "[email protected]",
}

在这里id值一直会返回,你也可以在第二个参数里设置{“_id”: 0}来剔除_id键值。

查询条件

$lt 、lte、gt、gte分别匹配< 、<=、 >、 >=,组合使用可查某个范围内的文档,此外“ne”用于匹配文档的键值不等于某个特定的值的情况。

OR查询

Mongodb中有两种方式进行or查询:


  • $in 用于查询一个键的多个值
  • $nin 用于返回不满足条件的结果
  • $or 更为通用,用来完成多个任意键的匹配值

db.record.find({“ticket_no”:{“$in”:[12,54,85]}})
db.record.find({“ticket_no”:{“$nin”:[126,554,215]}})
db.record.find({“$or”:[{“ticket_no”:12},{“winner”:true}]})

$not


  • “$not”是元条件句,可以用在任何其他条件之上。
  • 例如取模运算符“$mod”而言,它会将查询的值除以第一个给定的值,如果结果等于第二个给定的值那么就返回结果;

db.user.find({“id_nu”:{“$mod”:[5,1]}}) 返回1,6,11,16
db.user.find({“id_nu”:{“$not”:{“$mod”:[5,1]}}}) 返回2,3,4,5,7,8,9,10,12

条件句的规则

一个键可以有多个条件,但是一个键不能对应多个更新修改器,例如修改器文档不能是:
{“$inc”:{“age”:1},”$set”:{“age”:40}}, 因为对age属性修改了两次。但对于查询条件句就没有这种规则。

特定于类型的查询

null

    {
        "_id" : ObjectId("548546deab91bbcae368ddb2"),
        "y" : 1
    },
    {
        "_id" : ObjectId("548546deab91bbcae368ddc2"),
        "y" : null
    },
    {
        "_id" : ObjectId("548546deab91bbcae368ddb3"),
        "z" : 2
    },

按预期的方式去查y键为null的文档,它会查询到y键为空的文档,但与此同时也会返回y键不存在的文档,这并非我们想要的结果,但我们可以使用“$exists”条件判断键值是否存在:

db.c.find({“y”:{“$in”:[null],”$exists”:y}}) 这样就可以得到预期结果

正则表达式
正则表达式能够灵活有效的匹配字符串,Mongodb使用Perl兼容的正则表达式(PCRE)库来匹配正则表达式,PCRE支持的正则表达式都能被Mongodb所识别。

查询数组
- $all
如果要使用多个元素匹配数组,可以使用“$all”

{"_id":1, "fruit":["apple","banana","peach"]},
{"_id":2, "fruit":["apple","kumquat","orange"]},
{"_id":3, "fruit":["cherry","banana","apple"]}

db.food.find({“fruit”:{“$all”:[“”apple”, “”banana”]}}) 即可查询所有含有apple和banana的文档。

  • $size
    可以用于查询指定长度的数组:

db.food.find({“fruit”:{“$size”:3}})


  • $slice

db.user.findOne({criteria, {comments:{“$slice”:10}}}) comments数组前10条记录;
db.user.findOne({criteria, {comments:{“$slice”:-10}}}) comments数组后10条记录;
db.user.findOne({criteria, {comments:{“$slice”:[4,10]}}}) comments从第五条记录起的10条 记录,不足10条,就取从第五条起的所有记录。

查询内嵌文档

接下来看这样一个例子:

{
    "name":{ "first": "Joe", "last": "Schome" },
    "age": 24 }

如果要查询名字为Joe Schome的人时,那么可以执行db.find({“name”:{“first”:”Joe”,”last”:”Schome”}}),但此时如果我们再给name对象添加一个表示中间名字的字段时,如上命令就不能匹配整个文档了,就什么都匹配不到;我们可以使用点表示法来查询内嵌的键,db.find({“name.first”:”Joe”,”name.last”:”Schome”}),这样即便增加更多的键也能匹配到相应的记录;

对于更复杂的情况而言:

{   
    "content": ... "comments":[ { "author": "hank", "score": 5, "comment": "hank comment" }, { "author": "elvis", "score": 8, "comment": "elvis comment" } ] }

如果用db.people.find({“comments.author”: “hank”, “comments.score”:{“$gte”:6}}),那么此时会将匹配如上两条记录(类似于”或“),如果想要“与”的效果,那么使用“$elemMatch”将限定条件进行分组,如:db.people.find({“comments”: {“$elemMatch”:{“author”:”hank”,”score”:{“$gte”:6}}}})

$where
即可执行任务javascript作为查询的一部分。
$where的值可以是function、也可以是字符串等等。

db.C.find({“$where”:function(){return this.a == “1”}})与db.C.find({“$where”:”this.a == ‘1’”}})

注意:采用$where子句查询在速度上较常规查询慢的多。因文档需要从BSON转换成javascript对象,然后通过”$where”的表达式来运行。不用利用索引。可用常规查询做前置过滤,配置”$where”查询进行调优,可达到不牺牲性能的要求。

游标
MongoDB中find()函数返回一个游标,客户端通过对游标进行一些设置就能对查询结果进行有效地控制,如可以限制查询得到的结果数量、跳过部分结果、或对结果集按任意键进行排序等。如果我们通过变量保留find函数的返回值,其不会自动进行遍历显示操作,这样做,实际发生的是,调用完find后,此时Shell并不会去真正地访问数据库,而是等待开始要求获得结果的时候才向数据库发送查询请求!我们此时可以对这个游标进行各种设置,然后调用游标的hashNext()或next()方法,这样就会真正访问数据库,这是一个懒加载的过程。如下:

var cursor = db.coll.find();
while(cursor.hasNext()){
… var doc = cursor.next();
… // show the doc
… };

当调用cursor.hasNext()时,查询被发往数据库,默认会返回前100条文档或者前4M的数据(两者之中较小的),这样下次next或hasNext都是本地调用了!当这组数据被遍历完毕,hasNext会导致再次去访问数据库,直到所有结果被返回!

本文仅为本人阅读相关资料的笔记,如有不足之处,还请指出。

你可能感兴趣的:(mongodb,MongoDB游标,mongodb查询,mongodb嵌套,mongodb数组)