【问题标题】:creating covered index for aggregation framework为聚合框架创建覆盖索引
【发布时间】:2014-02-28 09:40:10
【问题描述】:

我在为我的查询创建索引时遇到问题,并且在网络上找不到任何类似的解决方案,所以也许你们中的一些人会帮助我。

为了简化问题,假设我们有具有某些属性的电话,

{
  "type":"Samsung",
  "model":"S3",
  "attributes":[{
     "value":"100",
     "name":"BatteryLife"
   },{
     "value":"200$",
     "name":"Price"
   }
}

带索引:{"type":1, "attributes.value":1}

每种类型都有数百万部手机,我想查找具有给定属性的给定类型的手机,我的查询如下所示:

db.Phone.aggregate([ 
{ "$match" : { "type" : "Samsung"}} , 
{ "$match" : { "attributes" : { "$all" : [ 
    { "value" : "100", "name" : "BatteryLife" } , 
    { "value" : "200$", "name" : "Price"}
                              ]}
             }
 }
])

而且它有效! 问题是这个查询效率很低,因为它只使用我的索引的第一部分,即“类型”(我有数百万个每种类型的电话),并且不使用“attributes.value”部分(类型+ attributes.value 几乎是唯一的,因此会显着降低复杂性)。

@编辑 感谢 Neil Lunn,我知道这是因为 index 仅在我的第一场比赛中使用,所以我必须更改我的查询。

@Edit2 我想我找到了解决方案:

db.Phone.aggregate([
{$match: {
    $and: [ 
        {type: "Samsung"}, 
        {attributes: {
           $all: [
                { "value":"100", "type" : "BatteryLife" },
                { "value":"200$", "type" : "Price" }
           ] 
        }}
    ]}
}])

+db.Phone.ensureIndex({type:1, attributes:1}),似乎有效。我想我们现在可以关门了。感谢您提供有关 $match 的提示。

【问题讨论】:

  • 对于覆盖索引,您需要将查询中使用的所有字段按顺序包含在内。这里的主要问题是您正在编写 multiple 匹配阶段,而所有条件都应仅在开始时处于 one 阶段。在第一次匹配之后,就不再使用 index。虽然您的问题中有很多信息,但它并没有描述您真正想要解决的问题。这是此处提出问题的最佳格式。
  • 解释我真正的问题太长了,但数据结构完全一样。感谢提示索引仅在第一场比赛中使用,我不知何故错过了。
  • 试图向您指出您根本没有解释您的问题。你已经被标记为接近投票。避免这种情况的最佳方法是将您的问题重新表述为人们可以解决的问题。
  • 我已经编辑了我的帖子,希望现在更清楚了。如果可能的话,我将尝试重新调整我的查询并将“type”和“attribute.value”放在一个匹配项中。请不要关闭这个话题。
  • 您应该从查询中删除 $and - 这里不需要它,因为“,”已经是“和”等价的。此外,您的查询语法可能不是您想要的。怀疑您打算使用 $elemMatch 来获得正确的结果。

标签: mongodb indexing aggregation-framework


【解决方案1】:

要充分利用索引,您需要在使用索引中所有字段的管道中及早进行 $match。并且避免使用 $and 运算符,因为它是不必要的,并且在当前 (2.4) 版本中可能导致索引没有被充分利用(幸运的是,在即将到来的 2.6 中修复了)。

但是,查询并不完全正确,因为您需要使用$elemMatch 来确保使用相同的元素来满足名称和值字段。

您的查询应该是:

db.Phone.aggregate([
{$match: {  type: "Samsung", 
           attributes: { $all: [
                {$elemMatch: {"value":"100", "type" : "BatteryLife" }},
                {$elemMatch: {"value":"200$", "type" : "Price" }}
           ] }
        }
}]);

现在,不是将成为一个覆盖查询,因为 attributes.value 和 name 是嵌入的,更不用说 name 不在索引中。

您需要索引为{"type":1, "attributes.value":1, "attributes.name":1} 以获得最佳性能,虽然它仍然不会被覆盖,但它会比现在更具选择性。

【讨论】:

    猜你喜欢
    • 2019-07-30
    • 2011-05-09
    • 1970-01-01
    • 2013-11-04
    • 1970-01-01
    • 2014-10-25
    • 2011-04-23
    • 2011-02-19
    • 1970-01-01
    相关资源
    最近更新 更多