mongodb查询语句时间范围_MongoDb查询

2ff34e647e2e3cdfd8dca593e17d9b0a.png

简介使用find或者findOne对数据库执行查询

使用$条件实现范围,集合包含,不等式和其他查询

使用$where子句用户复杂查询

查询会返回一个数据库游标,只有在需要数据的时候才会惰性的返回文档

针对游标执行的元操作,比如忽略一定数量的结果,限定返回结果的数量,对结果进行排序

find简介db.users.find()

db.users.find({‘name’:’nicolas’,’age’:20})

不带参数的find会返回全部文档。find可以指定查询文档,只返回匹配查询条件的文档,当查询文档含有多个K-V时连接条件为AND,第二个查询语句会返回name为nicolas并且age为20的文档指定返回的键db.users.find({},{‘name’:1,’age’:0})

有时我们并不需要将文档中的所有K-V都返回,这种情况我们可以使用find函数的第二个参数指定要返回的键。其中1代表将返回的文档按照该字段正向排序,0代表将返回的文档按照该字段逆向排序限制db.stock.find({‘in_stock’:’this.num_sold’})

查询文档必须是常量(在自己代码里可以使正常的变量),但是不能引用文档中其他键的值。故上面的这个查询是错误的

查询条件

比较操作符

$gt,$gte,$gt,gte是全部的比较操作符,分别对应,>=,可以将其组合起来查找一个范围的值。其中对于日期查询尤为有用,因为对日期的精确匹配终究是徒劳的。db.users.find({‘age’:{$lt:30,$gt:20}) 查找年龄大于20小于30的人

start = new Date(“01/01/2007”)

db.users.find(‘registered’:{$lt:start}) 查找注册日期在2007年1月1日之前的用户

OR查询$in可以用来查询键值在给定数组中的文档,与之相反的是$nin。这两者用来对单个键做OR查询db.users.find({‘name’:{$in:[‘nicolas’,’windylee’]}) 返回name为nicolas或windylee的文档

$or可以对多个键做OR查询,$or接受一个包含所有可能条件的数组作为参数,只要符合数组中任何一个元素的条件就会被查询出来,$or可以包含其他条件。普通的and兴的查询,总是尽可能的用最少的条件来限定结果的范围,or型的查询真好相反,第一个条件尽可能地匹配更多的文档db.users.find({$or:[{‘name’:{$in:[‘nicolas’,’windylee’]}},’age’:20]}) 查询name为nicolas或windylee或age为20的用户

$not查询

$not是元条件句,可以用在任何其他条件之上,表示对其他条件的结果取反。经常与正则表达式联合使用,用来查询不匹配正则表达式的文档db.users.find({‘age’:{$not:{$mod:[5,1]}}) 查询age值模5余数不为1的文档

条件句的规则

条件句是内层文档的键,修改器是外层文档的键,可对一个键应用多个条件,但是一个键不能对应多个更新修改器。例如{$inc:{'age':20},$set:{'age':40}}修改了age两次

特定于类型的查询

空值查询null

null不仅能够匹配到键值为null的文档,他还能匹配缺少这个键的所有文档

$exists

如果仅仅想匹配键值为null的文档,就需要使用到该关键字db.users.find({‘name’:{$exists:true}}) 返回name值不为空的文档

查询数组$ll

返回含有$all指向数组所有元素的文档db.users.find(‘course’:{$all:[‘english’,’chinese’]}) 返回课程含有english和chinese的用户

$size

返回数组长度为指定大小的文档,$size不能与其他查询子句组合(比如$gt)db.users.find({‘course’:{$size:3}}) 返回选了3门课的文档

$slice

返回一个数组的子集合。可以接受一个整型n,整数表示返回数组的前n条数据,负数表示返回数组的后n条数据;可以接受一个数组,数组的第一个元素表示偏移量,第二个元素表示获取的元素数量。除非特别声明,$slice返回文档中的所有键db.blog.posts.findOne(criteria,{‘comments’:{$slice,[1,2]}}) 默认会返回posts中的所有字段

查询内嵌文档

如果存在如下文档1

2

3

4

5

6

7{

'name':{

'first':'Jone'

'last':'Schmoe'

}

'age':45

}

要查询姓名为Jon Schmoe的人可以这样db.people.find({'name':{'first':'Jon','last':'Schmoe'}})这种方式采用全部匹配的规则,即查询条件中要包含内嵌文档的所有键,如果name内嵌文档中增加middle字段则上述查询条件就不起作用了。如果只想根据部分字段进行查询则需要点表达式db.people.find({'name.first':'Joe','name.last':'Schmoe'}),这也是带插入的文档不能包含’.’的原因

当文档变负责以后,即内嵌文档为数组时,如果有如下文档1

2

3

4

5

6

7

8

9

10

11

12

13

14

15{

'content':'...'

'comments':[

{

'author':'joe',

'score':3,

'comment':'nice post'

},

{

'author':'mary',

'score':6,

'comment':'terrible post'

}

]

}

如果继续使用点表达式db.blog.find({'comments.author':'jone','score':6})则第一个条件会在comments1中找到,第二个条件会在comments2中找到,所以会返回我们上面看到的文档。若要正确指定一组条件我们需要$elemMatch,这种模糊的命名条件句能用来部分指定匹配数组中的单个嵌入文档的限定条件,所以正确的写法应该是这样的db.blog.find({'comments':{$eleMatch:{'author:'Jone','score':'6}}})

$where查询

我们上面说过find的查询条件只能是常量,不能是文档中的值,如果我们查询条件为文档中的数据,那这时候我们就需要$where子句了,例如db.foo.find({$where:'this.x+this.y=10'})。$where速度要慢很多,除非必要不要使用该条件。

游标

数据库使用游标来返回find的执行结果,客户端队游标的实现通常能够对最终结果进行有效的控制,可以限制结果的数量,略过部分结果,根据任意方向任意键的组合对结果进行各种排序,或者执行其他一些功能强大的操作。当调用find的时候并不立即查询数据库,而是等待真正开始要求获得结果的时候才发送查询,这样我们就可以在执行之前给查询附加额外的选项

limit, skip, sort

limit限定返回结果的上限,skip跳过前n个匹配的文档;sort指定排序的键和排序条件,1为正序排序,-1为降序排序,如果指定了多个键,则按照多个键的顺序逐个排序,例如要按照username升序和age降序排序db.c.find().sort({'username':1,'age':-1})。find函数返回游标,这三个函数都可以组成链式操作。如果一个键对应不同的类型,则规定的类型顺序:最小值 < null < 数字(整形,长整形,双精度)< 字符串 < 对象/文旦 < 数组 < 二进制数据 < 对象ID < 布尔型 < 日期型 < 时间戳 < 正则表达式 < 最大值

避免使用skip略过大量结果

使用skip略过大量结果就会使操作变得非常缓慢,几乎所有的数据库都有这个问题,所以我们应尽量避免使用skip不用skip对结果分页

分页最简单的方式就是结合使用limit和skip两个函数,但我们可以有更好的解决方案。例如我们最获取文档时一般按照时间顺序进行排序,我们可以获取第一次获取的文档最后一个的时间,然后可以利用该时间值最为查询条件来获取下一页1

2

3

4

5

6var latest=null

while(page1.hasNext()){

latest=page1.next();

display(latest)

}

var page2=db.foo.find({'date':{$gt:latest.date}).sort('date':-1).limit(10)随机选取文档

一般做法是要查询文档总数,然后在0~n中选择一个随机数,使用skip跳过这些随机数来获取随机的一个文档。这样查询总数和使用skip略过文档都需要花费大量时间。我们可以再一开始就在文档中插入一个随机数的键,然后根据该随机数获取随机文档1

2db.people.insert({'name':'nicolas','random':Math.random()})

db.people.findOne({random:{$lt:Math.random()}})

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值