Mongodb mongo查询如何包括;或;使用索引

Mongodb mongo查询如何包括;或;使用索引,mongodb,indexing,Mongodb,Indexing,这是一个当查询具有“或”时如何创建有效索引的问题。如果没有“或”,我知道如何创建有效的索引 这是我的问题 db.collection.find({ 'msg.sendTime':{$gt:1}, 'msg.msgType':{$in:["chat","g_card"]}, $or:[{'msg.recvId':{$in:['xm80049258']}},{'msg.userId':'xm80049258'}], $orderby:{'msg.sendTime'

这是一个当查询具有“或”时如何创建有效索引的问题。如果没有“或”,我知道如何创建有效的索引

这是我的问题

db.collection.find({
    'msg.sendTime':{$gt:1},
    'msg.msgType':{$in:["chat","g_card"]},
     $or:[{'msg.recvId':{$in:['xm80049258']}},{'msg.userId':'xm80049258'}],
     $orderby:{'msg.sendTime':-1}})
在阅读了一些文章之后,我在msg.recvId和msg.userId上创建了两个单独的索引,这很有意义

  • 我想知道mongodb在什么时候执行“或”,它是否首先分割所有文档,然后使用msg.sendTime和msg.msgType

  • 在这种情况下,如何创建有效的索引?我应该创建索引(msg.sendTime:1、msg.msgType:1、msg.recvId:1)和 (msg.sendTime:1,msg.msgType:1,msg.userId:1)

  • 非常感谢。

    转述自:

    在计算$or表达式中的子句时,MongoDB要么执行集合扫描,要么在索引支持所有子句的情况下,MongoDB执行索引扫描。也就是说,为了让MongoDB使用索引计算$or表达式,索引必须支持$or表达式中的所有子句

    也来自:

    通常,MongoDB只使用一个索引来完成大多数查询。但是,$or查询的每个子句可能使用不同的索引

    这些段落对于
    $或
    查询的含义是:

    • find()
      查询中,只能使用一个索引。因此,最好创建一个与查询中的字段对齐的索引。否则,MongoDB将执行集合扫描
    • 除非查询是
      $或
      查询,否则MongoDB可以为每个
      $或
      术语使用一个索引
    • 总之,如果查询中有
      $或
      ,最好将
      $或
      术语作为顶级术语,并分别为每个术语创建索引
    所以要回答你的问题:

    我想知道mongodb在什么时候执行“或”,它是否首先分割所有文档,然后使用msg.sendTime和msg.msgType

    如果您的查询有一个顶级
    $或
    子句,MongoDB可以为每个子句使用一个索引。否则,它将执行收集扫描或半收集扫描。例如,如果您有索引:

    db.collection.createIndex({a: 1, b: 1})
    
    您可以创建两种常规类型的查询:

    1. <代码>$或
    不在查询的顶层 此查询可以使用索引,但不会执行:

    db.collection.find({a: 1, $or: [{b: 1}, {b: 2}]})
    
    由于查询的
    explain()
    输出为:

    > db.collection.explain().find({a: 1, $or: [{b: 1}, {b: 2}]})
    {
    "queryPlanner": {
    ...
            "indexBounds": {
            "a": [
                "[1.0, 1.0]"
            ],
            "b": [
                "[MinKey, MaxKey]"
            ]
    ...
    
    请注意,查询计划器无法使用
    b
    字段的适当边界,因为它正在执行半收集扫描(因为它正在从
    MinKey
    MaxKey
    搜索
    b
    ,即所有内容)。上面的查询计划器结果基本上是这样的:“查找
    a=1
    的文档,并扫描所有文档,查找值为
    1
    2
    b

    2. <查询顶层的code>$或
    但是,将
    $或
    子句拉到顶层:

    db.collection.find({$or: [{a: 1, b: 1}, {a: 1, b: 2}]})
    
    将生成此查询计划:

    > db.test.explain().find({$or: [{a: 1, b: 1}, {a: 1, b: 2}]})
    {
    "queryPlanner": {
    ...
        "winningPlan": {
        "stage": "SUBPLAN",
    ...
            "inputStages": [
                {
                "stage": "IXSCAN",
    ...
                "indexBounds": {
                    "a": [
                    "[1.0, 1.0]"
                    ],
                    "b": [
                    "[1.0, 1.0]"
                    ]
                }
                },
                {
                "stage": "IXSCAN",
    ...
                "indexBounds": {
                    "a": [
                    "[1.0, 1.0]"
                    ],
                    "b": [
                    "[2.0, 2.0]"
                    ]
    
    请注意,
    $或
    的每个术语都被视为一个单独的查询,每个查询都有一个严格的边界。因此,上面的查询计划是这样的:“查找
    a=1、b=1或
    a=1、b=2的文档”。可以想象,与前面的查询相比,此查询的性能要高得多

    关于第二个问题:

    在这种情况下,如何创建有效的索引?我应该创建索引(msg.sendTime:1,msg.msgType:1,msg.recvId:1)和(msg.sendTime:1,msg.msgType:1,msg.userId:1)

    如上所述,您需要将适当的查询与适当的索引结合起来以获得最佳结果。MongoDB可以使用您建议的两个索引,如果您重新安排查询,使
    $或
    位于查询的顶层,那么这两个索引将最有效

    我鼓励您了解MongoDB的
    explain()
    输出,因为它是确定查询是否使用正确索引的最佳工具

    您可能会发现有用的相关资源包括:


    看一看,然后看一看查询结果(并调整它,看看解释是如何变化的),我这样做的。但是我想知道mongo是如何分析查询包含“or”的,而不是为这个查询找到合适的索引的。而OrderBy最终总是发生在任何数据库中。非常感谢,@lovegupta。我明天会试试,:)找到另一件事:。与你分享。