zoukankan      html  css  js  c++  java
  • mongodb随机查询一条记录的正确方法!

    关于从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的方法了!

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

  • 相关阅读:
    桟错误分析方法
    gstreamer调试命令
    sqlite的事务和锁,很透彻的讲解 【转】
    严重: Exception starting filter struts2 java.lang.NullPointerException (转载)
    eclipse 快捷键
    POJ 1099 Square Ice
    HDU 1013 Digital Roots
    HDU 1087 Super Jumping! Jumping! Jumping!(动态规划)
    HDU 1159 Common Subsequence
    HDU 1069 Monkey and Banana(动态规划)
  • 原文地址:https://www.cnblogs.com/tgis/p/4731486.html
Copyright © 2011-2022 走看看