MongoDB聚合索引在没有提示的情况下不被使用

问题描述 投票:2回答:1

我有一个水果推车,有数百万行(为了保护罪名而改名。)

这些推车中的每一个都有一个所有者,一个品牌和一个模型,以及关于推车是否包含某些类型水果的多个Y或N字段。

我想生成模型列表,以及每个模型中有某些水果类型的推车数。

所以数据将是:

fruit.cart.insert(
{ 'owner' => 'Fred',   'make' => 'Toshiba', 'model' => 'fruitmaster 9000', 'have_apples' => 'Y', 'have_grapes' => 'N', 'have_peaches' => 'Y', ... },
{ 'owner' => 'Wilma',  'make' => 'Toshiba', 'model' => 'fruitmaster 9000', 'have_apples' => 'Y', 'have_grapes' => 'N', 'have_peaches' => 'N', ... },
{ 'owner' => 'Betty',  'make' => 'Toshiba', 'model' => 'fruitmaster 9000', 'have_apples' => 'N', 'have_grapes' => 'Y', 'have_peaches' => 'Y', ... },
{ 'owner' => 'Barney', 'make' => 'Toshiba', 'model' => 'fruitmaster X5',   'have_apples' => 'N', 'have_grapes' => 'N', 'have_peaches' => 'Y', ... },
{ 'owner' => 'Fred',   'make' => 'Honda',   'model' => 'T-1000',           'have_apples' => 'Y', 'have_grapes' => 'Y', 'have_peaches' => 'Y', ... },
{ 'owner' => 'Wilma',  'make' => 'Honda',   'model' => 'T-1000',           'have_apples' => 'N', 'have_grapes' => 'N', 'have_peaches' => 'N', ... },

而且我希望输出为:

{ 'make' => 'Toshiba', 'model' => 'fruitmaster 9000', 'count' => 3, 'apples_count' => 2, 'grapes_count' => 1, 'peaches_count' => 2, ... },
{ 'make' => 'Toshiba', 'model' => 'fruitmaster X5',   'count' => 1, 'apples_count' => 0, 'grapes_count' => 0, 'peaches_count' => 1, ... },
{ 'make' => 'Honda',   'model' => 'T-1000',           'count' => 2, 'apples_count' => 1, 'grapes_count' => 1, 'peaches_count' => 1, ... },

所以这是我的汇总查询:

{ '$group' =>
  {
    _id             =>  { 'model'  => '$model', },
    model           =>  { '$first' => '$model' },
    make            =>  { '$first' => '$make'  },
    count           =>  { '$sum'   =>  1 },
    oranges_count   =>  { '$sum'   => { '$cond' => [ { '$eq' => [ '$have_oranges', 'Y' ] }, 1, 0 ] }, },
    grapes_count    =>  { '$sum'   => { '$cond' => [ { '$eq' => [ '$have_grapes',  'Y' ] }, 1, 0 ] }, },
    peaches_count   =>  { '$sum'   => { '$cond' => [ { '$eq' => [ '$have_peaches', 'Y' ] }, 1, 0 ] }, },
    apples_count    =>  { '$sum'   => { '$cond' => [ { '$eq' => [ '$have_apples',  'Y' ] }, 1, 0 ] }, },
    pears_count     =>  { '$sum'   => { '$cond' => [ { '$eq' => [ '$have_pears',   'Y' ] }, 1, 0 ] }, },
  },
},

带索引:

db.cart.createIndex (
 {
   'have_pears'    : 1,
   'have_apples'   : 1,
   'have_oranges'  : 1,
   'have_grapes'   : 1,
   'have_peaches'  : 1,
   'make'          : 1,
   'model'         : 1,
 }, { background : true, name : 'fruit_counts' } );

如果我在未提供索引提示的情况下运行此命令,则它不使用索引,并且查询将永远花费:

  ...
  'queryPlanner' => {
    'indexFilterSet' => bless( do{\(my $o = 0)}, 'boolean' ),
    'namespace' => 'fruit.cart',
    'parsedQuery' => {},
    'plannerVersion' => 1,
    'rejectedPlans' => [],
    'winningPlan' => {
      'direction' => 'forward',
      'stage' => 'COLLSCAN'
    }
  }
  ...

带有提示,速度很快:

  {
    'ok' => '1',
    'stages' => [
      {
        '$cursor' => {
          'fields' => {
            '_id' => 0,
            'have_peaches' => 1,
            'have_apples' => 1,
            'have_oranges' => 1,
            'have_grapes' => 1,
            'have_pears' => 1,
            'model' => 1,
            'make' => 1
          },
          'query' => {},
          'queryPlanner' => {
            'indexFilterSet' => bless( do{\(my $o = 0)}, 'boolean' ),
            'namespace' => 'fruit.cart',
            'parsedQuery' => {},
            'plannerVersion' => 1,
            'rejectedPlans' => [],
            'winningPlan' => {
              'inputStage' => {
                'direction' => 'forward',
                'indexBounds' => {
                  'have_peaches' => [ '[MinKey, MaxKey]' ],
                  'have_apples' => [ '[MinKey, MaxKey]' ],
                  'have_oranges' => [ '[MinKey, MaxKey]' ],
                  'have_grapes' => [ '[MinKey, MaxKey]' ],
                  'have_pears' => [ '[MinKey, MaxKey]' ],
                  'model' => [ '[MinKey, MaxKey]' ],
                  'make' => [ '[MinKey, MaxKey]' ]
                },
                'indexName' => 'fruit_counts',
                'indexVersion' => 2,
                'isMultiKey' => $VAR1->[0]{'stages'}[0]{'$cursor'}{'queryPlanner'}{'indexFilterSet'},
                'isPartial' => $VAR1->[0]{'stages'}[0]{'$cursor'}{'queryPlanner'}{'indexFilterSet'},
                'isSparse' => $VAR1->[0]{'stages'}[0]{'$cursor'}{'queryPlanner'}{'indexFilterSet'},
                'isUnique' => $VAR1->[0]{'stages'}[0]{'$cursor'}{'queryPlanner'}{'indexFilterSet'},
                'keyPattern' => {
                  'have_peaches' => '1',
                  'have_apples' => '1',
                  'have_oranges' => '1',
                  'have_grapes' => '1',
                  'have_pears' => '1',
                  'model' => '1',
                  'make' => '1'
                },
                'multiKeyPaths' => {
                  'have_peaches' => [],
                  'have_apples' => [],
                  'have_oranges' => [],
                  'have_grapes' => [],
                  'have_pears' => [],
                  'model' => [],
                  'make' => []
                },
                'stage' => 'IXSCAN'
              },
              'stage' => 'PROJECTION',
              'transformBy' => {
                '_id' => 0,
                'have_peaches' => 1,
                'have_apples' => 1,
                'have_oranges' => 1,
                'have_grapes' => 1,
                'have_pears' => 1,
                'model' => 1,
                'make' => 1
              }
            }
          }
        }
      },

...

没有提示的documentdb:

'queryPlanner' => {
  'namespace' => 'fruit.cart',
  'plannerVersion' => 1,
  'winningPlan' => {
    'inputStage' => {
      'inputStage' => {
        'stage' => 'COLLSCAN'
      },
      'stage' => 'SORT'
    },
    'stage' => 'SORT_AGGREGATE'
  }
},

带有提示的documentdb:

MongoDB::DatabaseError: Cannot use Hint for this Query. Index is multi key index or sparse index and query is not optimized to use this index.

DOH !!!

所以我该怎么做,以致甚至不需要提示,然后使其在DocumentDB中工作?

indexing aggregate aws-documentdb
1个回答
0
投票

该错误具有误导性。 DocumentDB可以使用多键索引提示,但是查询本身必须包含与索引匹配的字段,否则您将看到此消息。即使提示单个键索引,您也会看到相同的消息,但是查询不包含索引字段。

© www.soinside.com 2019 - 2024. All rights reserved.