mongodb 随机查询
来源:互联网 发布:电子相册制作软件 编辑:程序博客网 时间:2024/04/30 04:08
mongodb的随机查询不像mysql一样可以利用rand()函数,取随机数查询数据,mongodb在查询中,并没有类似rand()的查询方法 (mongodb当前版本1.6.3)
题外话: mysql的rand在执行效率上有一定问题 sql 需要优化 详见
下面是一个具体的例子和解决方案
部分参照官网的mongodb cookbook 文章 The Random Attribute译过来的,官网废话太多了
假如你现在执行如下mongodb查询
1
photos.
find
({
"author"
:
"John Doe"
})
查询结果是获取author为John Doe的所有数据,假如你只是想获取随机的几条数据,你可以查询后,计算数据总条数,然后rand结果数组的几条,就可以实现了
但对于几十万数据或高频度查询来说,这种查询几乎是致命的.
所以在你向数据库里插入数据的时候,可以预先定义一个RA字段(随机属性字段),插入RA字段一个随机数,用随机数查询
1
> db.docs.drop()
2
> db.docs.save( { key : 1, ..., random : Math.random() } )
3
> db.docs.save( { key : 1, ..., random : Math.random() } )
4
> db.docs.save( { key : 2, ..., random : Math.random() } )
5
... many
more
insertions with
'key : 2'
...
6
> db.docs.save( { key : 2, ..., random : Math.random() } )
7
...
Math.random()实现了js中的随机数方法, 如果你使用的是Math.random() ,会获取一个0~1之间的随机数
01
> Math.random()
02
0.09635701317617418
03
> Math.random()
04
0.9123326061270348
05
> Math.random()
06
0.06640002172592852
07
...
08
{
"_id"
: ObjectId(
"4bfa81198cf5fc1002a42b91"
),
"key"
: 2,
"random"
: 0.23578915913357468}
09
...
10
{
"_id"
: ObjectId(
"4bfa81198cf5fc1002a42b93"
),
"key"
: 2,
"random"
: 0.8983254666113549 }
如果你使用了上面的解决方案,那么你还要给随机的字段的数据库索引,比如上面的random
1.随机查询单条记录
如果想随机查询单条记录,那么只需要变更一下请求,对RA字段添加适当的过滤条件. 下面尝试着查询跟RA字段中的值最接近的记录
1
> rand = Math.random()
2
> result = db.docs.findOne( { key : 2, random : { $gte : rand } } )
3
>
if
( result == null ) {
4
> result = db.docs.findOne( { key : 2, random : { $lte : rand } } )
5
> }
1.取rand 随机数
2.查询random字段中大于rand的单条记录
3.判断有无数据,无数据则查询小于rand的单条记录
使用这种方法的时候,很重要的一点是建立数据库索引
1
> db.docs.ensureIndex( { key : 1, random :1 } )
2. 对样本数据进行map / reduce 查询
如果数据和计算量过大,可以取样本数据,然后对结果的RA字段进行如上过滤处理
01
> db.docs.drop()
02
>
for
(i=0; i < 10000; i++) { db.docs.save( { key : i % 10, rand : Math.random() } ) }
03
> m =
function
() { emit(this.key, 1); }
04
> r =
function
(k, vals) {
05
var
sum
=0;
06
for
(var i
in
vals)
sum
+= vals[i];
07
return
sum
;
08
}
09
> sample = 0.1
10
> res = db.docs.mapReduce(m, r, { query : { key : 2, rand : { $lte: sample } } })
mongodb 将会执行query查询,只有符合条件的10%数据才会执行mapper方法,相较于全文查询,运行时间会大大减少
我本地测试查询key为2 ,且RA字段小于0.1的数据计数为98 很接近100 官网的数据为85,本地结果如下
01
{
02
"result"
:
"tmp.mr.mapreduce_1288863869_7"
,
03
"timeMillis"
: 25,
04
"counts"
: {
05
"input"
: 98,
06
"emit"
: 98,
07
"output"
: 1
08
},
09
"ok"
: 1,
10
}
默认情况下map/reduce生成的collection是临时的,只要你断掉本次连接就会自动删除,所以查询结果,仅当次连接有效
.
01
> res = db.docs.mapReduce(m, r, { query : { rand : { $lte : 0.1 } } })
02
03
#mongodb 执行查询语句,根据查询条件获取10%的样本数据 , 根据上述的查询,执行结果应该类似如下,本地测试数据
04
...
05
> db[res.result].
find
()
06
{
"_id"
: 0,
"value"
: 98 }
07
{
"_id"
: 1,
"value"
: 103 }
08
{
"_id"
: 2,
"value"
: 89 }
09
{
"_id"
: 3,
"value"
: 99 }
10
{
"_id"
: 4,
"value"
: 100 }
11
{
"_id"
: 5,
"value"
: 115 }
12
{
"_id"
: 6,
"value"
: 103 }
13
{
"_id"
: 7,
"value"
: 92 }
14
{
"_id"
: 8,
"value"
: 111 }
15
{
"_id"
: 9,
"value"
: 108 }
在map/reduce 查询随机数据的实例中,可以不必像第一种方法为属性创建库索引
附加说明
使用Math.random()插入数据进行查询是,概率的数会偏大,所以不一定能保证查询的结果是按照概率均匀分布的
1
> db.docs.save( { key : 1, random : Math.random() } )
2
> db.docs.save( { key : 1, random : Math.random() } )
3
> db.docs.
find
()
4
{
"_id"
: ObjectId(
"4bfa9585cffdb770c08e7cc9"
),
"key"
: 1,
"random"
: 0.9988383572723725 }
5
{
"_id"
: ObjectId(
"4bfa9586cffdb770c08e7cca"
),
"key"
: 1,
"random"
: 0.8
- mongodb 随机查询
- ndoejs+mongodb 开发4: 随机查询一条数据
- 随机查询
- 随机查询
- mongodb查询
- mongodb 查询
- mongodb查询
- MongoDB查询
- mongodb查询
- mongodb查询
- mongodb查询
- MongoDB -- 查询
- mongodb查询
- MongoDB查询
- MongoDB查询
- mongodb查询
- mongodb查询
- MongoDB查询
- Hadoop源代码分析(三)RPC
- Qemu运行错误ACPI.SYS 000000FE
- 一次代码review引发的关于单例模式的思考
- Ubuntu12.04下adb android设备
- Web App安装
- mongodb 随机查询
- Bugzilla安装
- imx53 android patch r10.4 for android 2.3.7_r1
- iOS开发 XCode4 iOS5 改变UINavigationController的UINavigationBar的高度和背景图片 V1
- Python学习笔记(4)-- 网络编程(1)-- socket
- 解决方案"System.InvalidOperationException: 配置有 NoSecurityChanges 标志的 AppDomainManager 修改了 AppDomain 的安全状
- Perl模块安装
- LM4F120 2.5.1 异常状态
- rman 增量备份