$exists 和 $in/nin 算作非前缀排序的相等查询吗?

Do $exists and $in/nin count as equality queries for non-prefix sorts?

http://docs.mongodb.org/manual/tutorial/sort-results-with-indexes/#sort-and-non-prefix-subset-of-an-index

指数

{ a: 1, b: 1, c: 1}

支持此查询:

db.data.find( { b: 3, a: 4 } ).sort( { c: 1 } )

是否也支持

db.data.find( { b: 3, a: {$exists: true} } ).sort( { c: 1 } )
db.data.find( { b: {$in: [3,4]}, a: 4 } ).sort( { c: 1 } )
db.data.find( { b: {$nin: [3,4]}, a: {$exists: false} } ).sort( { c: 1 } )

所有查询都将使用索引进行检索,但只有第二个用于排序,因为其他查询使用的运算符不是相等条件。

您可以通过 运行 使用 .explain()

的查询来证明这一点

请参阅下面这 3 个查询的解释(来自 MongoDB 2.6.3)的输出,省略了不必要的字段。 "cursor" 显示使用的索引,"indexBounds" 显示索引键的上下限。 "scanAndOrder" : false表示索引也被用于排序

"indexBounds" 很重要,因为您可以看到相等条件 - 例如,请注意 "$exists" : false 是一个相等条件(为空)并且可能会在 "$exists" : true 时使用索引是一个范围。

另见 documentation on explain,它对于理解索引使用和诊断性能问题非常有用。

db.data.find( { b: 3, a: {$exists: true} } ).sort( { c: 1 } ).explain()
{
    "cursor" : "BtreeCursor a_1_b_1_c_1",
    "scanAndOrder" : true,
    "indexBounds" : {
        "a" : [
            [
                {
                    "$minElement" : 1
                },
                {
                    "$maxElement" : 1
                }
            ]
        ],
        "b" : [
            [
                3,
                3
            ]
        ],
        "c" : [
            [
                {
                    "$minElement" : 1
                },
                {
                    "$maxElement" : 1
                }
            ]
        ]
    },
}

,

db.data.find( { b: {$in: [3,4]}, a: 4 } ).sort( { c: 1 } ).explain()
{
    "clauses" : [
        {
            "cursor" : "BtreeCursor a_1_b_1_c_1",
            "scanAndOrder" : false,
            "indexBounds" : {
                "a" : [
                    [
                        4,
                        4
                    ]
                ],
                "b" : [
                    [
                        3,
                        3
                    ]
                ],
                "c" : [
                    [
                        {
                            "$minElement" : 1
                        },
                        {
                            "$maxElement" : 1
                        }
                    ]
                ]
            }
        },
        {
            "cursor" : "BtreeCursor a_1_b_1_c_1",
            "scanAndOrder" : false,
            "indexBounds" : {
                "a" : [
                    [
                        4,
                        4
                    ]
                ],
                "b" : [
                    [
                        4,
                        4
                    ]
                ],
                "c" : [
                    [
                        {
                            "$minElement" : 1
                        },
                        {
                            "$maxElement" : 1
                        }
                    ]
                ]
            }
        }
    ],
}    

,

db.data.find( { b: {$nin: [3,4]}, a: {$exists: false} } ).sort( { c: 1 } ).explain()
{
    "cursor" : "BtreeCursor a_1_b_1_c_1",
    "scanAndOrder" : true,        
    "indexBounds" : {
        "a" : [
            [
                null,
                null
            ]
        ],
        "b" : [
            [
                {
                    "$minElement" : 1
                },
                3
            ],
            [
                3,
                4
            ],
            [
                4,
                {
                    "$maxElement" : 1
                }
            ]
        ],
        "c" : [
            [
                {
                    "$minElement" : 1
                },
                {
                    "$maxElement" : 1
                }
            ]
        ]
    },
}