关于从mongodb库中随机取出一条记录的方法的博文很多,其中都提到了下面三种方法:

1、skip过随机数量的记录。

DBCursor cursor = coll.find(query);
int rint = random.nextInt(cursor.count());
cursor.skip(rint);
DBObject word = null;
if(cursor.hasNext()){
word = cursor.next();
cursor.close();
}

很多人说不推荐这种做法,如果数据量不是那么巨大,10万个记录以内完全可以使用这种方法。

其实让我写存储引擎的话,我肯定把这个方法搞成最快的。只查询,又不排序。用作查询的条件建好索引后,至少和方法2一样快。通过索引进行物理skip很容易直接就定位到要找的数据了。

2、增加一个random数值字段。

var random=Math.random();
var result=db.user.findOne({"random":{"$lt":random}});
if(result==null){
result=db.user.findOne({"random":{"$gte":random}});
}

很多人说这是效率较高的一种可行方法,但是如果你信了,又不加验证,那真叫坑了爹了!下面我们就分析一下。

findOne的机制是取出查询结果的第一条。这有什么问题看出来了吗?

内部的查询结果是按random字段排序的吗?问题显然不是那么好回答吧!通过试验发现:如果不建立索引,查询的结果是按照存储顺序排的。也就是说不管查询条件是小于,还是大于等于,都会取到符合条件的最早入库的记录。这大大降低了随机性,有没有啊。如果建立索引,查询的结果是按照random由小到大排序的,此时如果用小于等于条件,始终取回来的是random值最小的值。这就没有随机性了,是不是呢。也就是说,如果random升序需要使用大于条件,如果降序需要使用小于条件。但是没有指定排序的时候内部怎么给排序,你敢肯定吗?如果不敢肯定,是不是就得指定排序方式。从底层来说,你指定的排序方式跟索引的物理存放顺序一致才能达到最高的效率。

3、增加一个random空间位置字段。

 db.coll.ensureIndex({  random: '2d' })

 result = db.coll.findOne({ random: { $near: [Math.random(), 0] } })

将random建立为多值字段,两值得就可以,建立索引的时候当地理位置使用。取值的时候随机生成一个坐标,然后取离这个点最近一个值。

很多人把这个方法也列在推荐方法中,但是真的是高效率的方法吗?这个方法比较麻烦,很多人应该都没验证,直接抄写到自己博客了。其实用脑袋想想,这个方法比第二个方法更不靠谱呢。可以自己思考一种算法——在一群坐标中找出离某个坐标最近的一个坐标。好难哦,坐标点哎,他们本身并没有一个大小关系,也就是说没有天然的顺序。那些牛逼的查找算法都是基于排序的(基于哈希的本质也是基于排序的)。

那么怎么办?方法一:对两个分量建立两个索引。然后以查询点为中心点构建一个较小的矩形区域,查询的时候就是两个分量的范围的与关系。如果没查到结果扩大矩形区域,如果查询的结果过多,缩小矩形区域,这里就可以用二分法了。然后在矩形区域内精确计算距离。方法二:空间点按照相互距离聚类,然后将类别中心存储起来,然后采用方法一找到一个最近的类别中心,然后再在这个内别中使用方法一。方法三:求出所有点的外接矩形,然后把区域等分成4块的方法构建4叉树索引。构建过程就是把某个区域分成四等分,再把其中一份分成4等分,直到每个区域的点数少于给定值。这样查询的时候每层确定一次范围。最后一层暴力计算距离。我是想不出来更牛B的方法了!

可见最近空间距离的计算不轻松啊!

mongodb随机查询一条记录的正确方法!的更多相关文章

  1. 【面经】面试官:如何以最高的效率从MySQL中随机查询一条记录?

    写在前面 MySQL数据库在互联网行业使用的比较多,有些小伙伴可能会认为MySQL数据库比较小,存储不了很多的数据.其实,这些小伙伴是真的不了解MySQL.MySQL的小不是说使用MySQL存储的数据 ...

  2. mysql_oracle_随机查询几条记录

    数据库的随机查询SQL 1. Oracle,随机查询20条 select * from ( select  *  from 表名 order by dbms_random.value ) where ...

  3. 随机提取N条记录[多种数据库方法]

    随机提取10条记录的例子: Sql server: select top 10 * from 表 order by newid() Access: SELECT top 10 * FROM 表 ORD ...

  4. mongodb索引--1亿条记录的查询从55.7秒到毫秒级别<补充版>

    从头开始,验证mongodb的索引的好处.(window7环境下) 下载mongodb服务器,并解压到d盘,并使用以下命令启动 mongod --dbpath D:\mongodb\data mong ...

  5. TODO:从数据库中随机抽取一条记录

    TODO:从数据库中随机抽取一条记录 1.最直接,最粗暴的方法先计算记录的总数,然后选择一个从0到记录总数之间的随机数n,利用skip跳过n条记录,这是效率低下的的方法,首先的记录总数,在用skip会 ...

  6. mysql 随机选取一条记录

    要从tablename表中随机提取一条记录,大家一般的写法就是:SELECT * FROM tablename ORDER BY RAND() LIMIT 1. 1 2 3 4 5 6 7 8 9 1 ...

  7. Oracle整合Mybatis实现list数据插入时,存在就更新,不存在就插入以及随机抽取一条记录

    作者:故事我忘了¢个人微信公众号:程序猿的月光宝盒 目录 Oracle整合Mybatis实现list数据插入时,存在就更新,不存在就插入 entity 对应表中字段,如不对应,在xml中起别名 map ...

  8. 【转】oracle 中随机取一条记录的两种方法

    oracle 中随机取一条记录的两种方法 V_COUNT INT:=0; V_NUM INT :=0; 1:TBL_MYTABLE 表中要有一个值连续且唯一的列FID BEGIN SELECT COU ...

  9. mysql 查询一条记录的下一条和上一条记录

    如果ID是主键或者有索引,可以直接查找: 方法一: 查询上一条记录的SQL语句(如果有其他的查询条件记得加上other_conditions以免出现不必要的错误): select * from tab ...

随机推荐

  1. Head First HTML与CSS、XHTML (中文版).(Elisabeth Freeman) PDF扫描版​

    面对那些晦涩的html书你不禁要问:“难道要成为专家之后才能读懂这些?”那么,你应该选择<head first html与css.xhtml(中文版)>真正来学习html.这本书对你来说, ...

  2. TriggerAction扩展----ExInvokeCommandAction

    Wp&Win8中使用命令绑定时,除了Button控件自带命令绑定,其他的时候是用Interactivity库中的InvokeCommandAction实现的(Win8 需要额外安装第三方NuG ...

  3. 去掉html标签方法

    public static string CleanHtml(string strHtml) { strHtml = Regex.Replace(strHtml, @"(\<scrip ...

  4. 二、安装Node.js和npm

    1.Note的各个版本官方下载地址: https://nodejs.org/en/download/releases/ 这里我们选择7.6版本为例进行下载安装: 根据自己的情况下载对应的msi安装包 ...

  5. windows下安装newman

    1.下载安装node.js,下载地址::https://nodejs.org/en/download/,这里我下载的为v10.15.0-x64.msi,下载后直接安装即可,安装完后可输入node -v ...

  6. 1. UML统一建模语言

    (1)UML概述: 建模: 对现实系统进行适当的过滤, 用适当的表现规则描述出简洁的模型. 建模是一种深入解决问题的方法. UML: UML(United Modeling Language, 统一建 ...

  7. SDK 开发 .a .framework .bundle (xcode引用) 依赖sdk工程

    一. 静态库.a 1.创建静态库工程 Cocoa Touch Static Libray  ,然后可以创建一个测试视图 TestView 2.暴露头文件 -> Build Phases--> ...

  8. Liunx 挂载磁盘

    查看已经挂载的分区和文件系统类型 [root@VM_101_18212122_centos /]# df -T Filesystem Type 1K-blocks Used Available Use ...

  9. C++_类入门4-String类

    很多应用程序都需要处理字符串.C语言在string.h(C++中为cstring)中提供了一系列的字符串函数,很多早期的C++实现为处理字符串提供了自己的类. string类是由头文件string支持 ...

  10. LeetCode153.寻找旋转排序数组中的最小值

    153.寻找旋转排序数组中的最小值 描述 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 请找出 ...