2

我在 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',
 ),
4

2 回答 2

0

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

于 2013-05-31T23:56:12.273 回答
0

复合索引不可用于反向排序,但不必担心在这种情况下它可能无济于事,如果你在 $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 子句,那么 or 列表的每个部分都将单独使用索引。因此,不要使用 in:[] 条件,而是使用 or:[] 并定义与 $mendor["t"] 数组中的值一样多的不同查询。在 mongoshell 中没有用,但我相信它应该,也许我错过了一些东西。

于 2013-05-28T15:37:36.237 回答