在多键上排序时如何进行扫描和排序0

时间:2013-05-28 13:55:38

标签: php mongodb

我在mongodb上有大量文档,这是一个虚拟插入

 array (
  '_id' => new MongoId("51a449866803fa680a000002"),
  'a' => 'dweddwe',
  'b' => 'asdasdad',
  'c' => 
  array (
    '0' => 'car',
  ),
  'u' => '1',
  'x' => 
  array (
   '0' => '51a0c0356803fa890a000003',
   '1' => '51a0c0356803fa890a000003',
  ),
  'y' => 'merto',
)

我的mongo数据库中插入的文档超过100个,问题是,当我使用此代码和索引(如x_1__id_1或其他任何方式)时,我总是得到[scanAndOrder] => 1,我有不知道可能是什么问题或解决方案,我怎样才能以有效的方式对其进行排序?谢谢你:))

$m->cars->post->find(array("x" => array('$in' => $mendor["t"])))->limit(10)->sort(array("_id" => -1))->explain();

这是$ mendor [“t”],

't' => 
  array (
   '0' => '519f2de16803fabd0d000001',
   '1' => '51a0bf996803fa890a000001',
   '2' => '519f2db96803fad20d000001',
   '3' => '519f1cc56803fa960d000001',
 ),

2 个答案:

答案 0 :(得分:0)

Compund索引不能用于反向排序,但是如果你在$ mendor [“t”]中有一个真正的列表,那么在这种情况下它不会有任何帮助。 我用简单的文档制作了一个名为t的测试集合,如:

{ "_id" : ObjectId("51a4c2c75e0733e8428ab2c0"), "x" : [ 1, 2, 3, 4 ] }
{ "_id" : ObjectId("51a4c2c95e0733e8428ab2c1"), "x" : [ 1, 2, 3, 6 ] }
{ "_id" : ObjectId("51a4c2cd5e0733e8428ab2c2"), "x" : [ 1, 4, 3, 6 ] }

我创建了索引:x_1__id_1

对于查询:

db.t.find({x:3}).hint("x_1__id_1").sort({_id:1}).explain()
{
    "cursor" : "BtreeCursor x_1__id_1",
    "isMultiKey" : true,
    "n" : 14,
    "nscannedObjects" : 14,
    "nscanned" : 14,
    "nscannedObjectsAllPlans" : 14,
    "nscannedAllPlans" : 14,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 0,
    "indexBounds" : {
        "x" : [
            [
                3,
                3
            ]
        ],
        "_id" : [
            [
                {
                    "$minElement" : 1
                },
                {
                    "$maxElement" : 1
                }
            ]
        ]
    },
    "server" : ""
}

所以它可以让你的查询工作,但是:

db.t.find({x:{$in:[3,4]}}).hint("x_1__id_1").sort({_id:1}).explain()
{
    "cursor" : "BtreeCursor x_1__id_1 multi",
    "isMultiKey" : true,
    "n" : 16,
    "nscannedObjects" : 28,
    "nscanned" : 28,
    "nscannedObjectsAllPlans" : 28,
    "nscannedAllPlans" : 28,
    "scanAndOrder" : true,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 0,
    "indexBounds" : {
        "x" : [
            [
                3,
                3
            ],
            [
                4,
                4
            ]
        ],
        "_id" : [
            [
                {
                    "$minElement" : 1
                },
                {
                    "$maxElement" : 1
                }
            ]
        ]
    },
    "server" : ""
}

这是合理的,而使用的多键索引是作为分离的索引键存储在数组中的值。请参阅文档:http://docs.mongodb.org/manual/core/indexes/#multikey-indexes

因此,从不同的键收集的不同部分将由引擎合并而不是分类。如果您使用的标准与我的第一个查询类似,那么只需搜索一个数组而不是数组。比它将scanAndOrder:false。可能你必须创建一个x_1_ id -1索引。

有一种解决方法,但它有点难看。如果对查询使用or子句,则或者列表的每个部分将单独使用索引用法。因此,不要使用in:[]条件,而是使用or:[]并在$ mendor [“t”]数组中定义尽可能多的不同查询。在mongoshell没有用,但我确信它应该,也许我错过了一些东西。

答案 1 :(得分:0)

x,_id上有复合索引。 _id的顺序不是绝对的,而是在x值的上下文中。在您的查询中,您正在为特定的x值选择一组文档,然后按_id排序。因此,为了获得订单,它必须基于_id值对结果进行实际排序,而不是仅使用索引顺序。这就是你看到的扫描和命令是真的。希望这会有所帮助。