Mongodb查询

参考

MongoDB权威指南(第2版)

Mongodb Documentation

前言

在Mongodb中查询的方法常用的有两个findfindOne,前者返回所有匹配的文档,而后者返回匹配的第一个文档,它的用法很简单。第一个是它的查询条件,第二个是指定返回文档中字段的过滤器,这个的作用也就是说你想显示哪些字段或者你想不显示哪些字段。并且该方法返回的是一个Cursor对象。

需要注意的是,find方法查询的时候会查询数组的成员是否符合查询条件,如果查询条件符合,将会把整个数组返回。

db.collection.find(query, projection)

比如下面通过find语句,查询blog集合中作者为xsscript的文档,并且只返回作者和文章内容。

db.blog.find({author: 'xsscript'}, {author: 1, content: 1});

在过滤器中,你如果没有显示的声明不返回_id键,默认都会返回,除非显示的声明_id: 0。还有比如在过滤器中设置了auther: 1,那么只会返回_idauther两个键值,如果你只需要过滤一些不希望显示的值,那么就在过滤器中设置你需要不显示的键并把值设为0,这样文档中所有的值除了你设置不返回的都会返回。

如果你需要查询多个值匹配的文档,你可以像下面代码所示,把你需要的条件都写在第一个参数对象中,这样的查询其实是AND查询,下面的代码查询了集合中所有文档中作者是xsscript,时间为20170701,并且只返回作者、时间、内容,其中_id不显示。

db.blog.find({author: 'xsscript', time: 20170701},{
    author: 1,
    content: 1,
    time: 1,
    _id: 0
})

条件查询

一个键可以存在多个条件

比较操作符

$lt$ltegtgte这四个比较查询符分别表示<<=>>=,可以将其比较查询符组合起来查询,这个代码对于范围查询的筛选非常有用。比如我需要查询年龄大于17岁到25岁之间的文档,代码如下面所示:

db.test.find({
    age: {
        $gt: 18,
        $lte: 25
    }
});
包含查询操作符

$in操作符是多个条件针对一个键的值进行匹配,比如我需要查询年龄在18、20、25、30的文档,就可以使用$in操作符:

db.test.find({
    age: {
        $in: [18, 20, 25, 30]
    }
});

$or操作符是多个条件匹配多个键值,它非常有用,就有点类似于JS中的||符号,比如我需要查询一个文档中含有age: 18或者含有name: joe的文档,就可以使用$or操作符,比如下面的代码

db.test.find({
    $or: [
        {age: 18},
        {name: 'joe'}
    ]
})

对应$in$or操作符的还有一个反义的即$nin$nor操作符,后两个操作符的意思是返回不包含查询条件匹配到的所有文档,但是注意,如果在使用后者的两个操作符进行查询的话,会存在一个问题需要注意,比如下面

    db.test.find({
        a: {
            $nin: [1,2,3]
        }
    })

上面的代码理想的意思是匹配a键的值非1,2,3,但是返回的文档中可能会存在没有a键的文档。

取反操作符

$not取反操作符,用于对结果进行取反,我们可以实现一个和$nin操作符相同的操作来演示$not的效果:

db.test.find({
    a: {
        $not: {
            $in: [1,2,3]
        }
    }
})
多条件查询操作符

$and操作符是用于多条件查询的,但是它更加灵活,比如下面匹配文档中含有a:1author: xsscript的键值对:

db.test.find({
    $and: [
        {a: 1},
        {author: 'xsscript'}
    ]
})

数组查询

在Mongodb中,查询数组可以通过下面的方式查询,比如下面的例子:

文档

{
    a: ['one','two']
}

代码

db.test.find({
    a: ['one', 'two']
})

上面的代码能够匹配文档,但是需要注意的一点匹配的条件顺序如果和文档不一致,就不能匹配文档。

数组包含操作符

$all操作符的作用和行为都与上面的代码一致,但是有一点不同,就是$all操作符包含的数组成员不分顺序,只要数组含有这两个值就匹配成功:

文档

{
    a: ['one','two']
}

代码

db.test.find({
    a: {
        $all: ['two', 'one']
    }
})
数组长度操作符

$size操作符用于匹配指定数组长度的文档,比如下面的代码:

文档

{
    a: ['one','two']
}

代码

db.test.find({
    a: {
        $size: 2    
    }
})
返回数组成员截取符

$slice操作符用于指定数组返回的成员数,可以是正数和负数,正数从第一个开始截取,负数从倒数第一开始截取。

文档

{
    a: ['one','two']
}

代码

db.test.find({
    a: {
        $slice: 1
    }
})
数组比较操作符

$elemMatch操作符是针对数组成员进行比较的操作符,如果不使用这个操作符将出现一些问题,比如下面,我想通过大于10并且小于20来匹配文档1的数组成员,但是这样通常得不到想要的效果,这是因为文档1的a键是一个数组,里面成员符合条件,里面的成员5小于20,成员25大于10。

文档1

{
    a: [5,25]
}

代码:

db.test.find({
    a: {
        $lt: 20,
        $gt: 10
    }
});

但是如果使用了$elemMatch操作符就不会存在这样的问题,它会把所有的条件对数组成员进行匹配:

{
    a: [5,25]
}

代码:

db.test.find({
    a: {
        $elemMatch: {
            $lt: 20,
            $gt: 10
        }
    }
});
$占位符

当我们匹配非数组键值对的时候,我们需要返回的只需要的键值对是这样操作的:

db.test.find({author: 'xsscript'}, {author: 1});

那如果我们数组呢?如果我们数组按照上面的方法呢?可能只会返回每个数组成员中指定显示的值,而我们需要的是只返回匹配到的数组成员,那么这个时候就可以用占位符$了,它相当于是匹配到的文档中的数组成员下标占位符。

文档

{
    a: [
        {b: 'one'},
        {c: 'two'}
    ]
}
db.test.find({
    'a.b' : 'one'
}, {
    'a.$.b' 1
})

上面的代码返回的文档就会正确了

{
    a: [
        {b: 'one'}
    ]
}

文完

文档信息

发表评论

电子邮件地址不会被公开。 必填项已用*标注