mongodb 中的Multikey Index Bounds解释$elemMatch

首先说一下 $elemMatch的用法:

{ _id: 1, results: [ 82, 85, 88 ] }

{ _id: 2, results: [ 75, 88, 89 ] }

$elemMatch是匹配document 中数组中至少有一个元素满足$elemMatch中的所有条件,例如:

db.scores.find(
   { results: { $elemMatch: { $gte: 80, $lt: 85 } } }
)

查询结果为:

{ "_id" : 1, "results" : [ 82, 85, 88 ] }

结下来解释一下(Multikey Index Bounds):
在一个查询期间,索引的扫描范围定义了部分索引为了搜索,当多个(条件)predicates 超过一个索引存在时:mongodb 将试图去合并这些(条件)predicates的边界,要么通过求交集的方法合并
要么通过组合的方法,为了去产生一个比较小的扫描范围。
给定一个索引数组字段,考虑到在一个查询中,在一个数组中指定了多个(条件)predicates并且可以使用 Multikey Index。
if $elemMatch 中有多个(条件)predicates ,mongodb会合并 Multikey Index的边界。因此,会有$elemMatch是匹配document 中数组中至少有一个元素满足$elemMatch中的所有条件。

继续上面的例子,逐个条件边界的范围:
大于等于80($gte:80)的边界为[80,inf];
小于85
($lt:85)的边界为[-inf,85]。
由于使用了$
elemMatch组织多个条件查询,mongodb查询的边界为results:[[80,85)]。

我们在来看一下(Compound Bounds for Multikey Index)

由于上面的查询条件可以求交集,但是,假如还有一种情况,有两个数组:

_id1results828588 ],scores:[66,77,88] }

_id2results758889 ] ,scores:[77,44,22]}

查询条件为:

db.scores.find(
   { results: { $gte: 85 },scores:{$lt:60}}
)
他们是没有交集的,在这种情况下,索引的边界是怎么样的呢?就继续看
Compound Bounds for Multikey Index
把同一个数组中的不同索引键的边界混合在一起的条件如下:
  这些索引的keys必须有相同的字段路径,但是不包括字段的names
  这个查询必须在指定的字段路径的这个特定的字段上面使用$elemMatch
还是看例子:
{
  _id: 1,
  item: "ABC",
  ratings: [ { score: 2, by: "mn" }, { score: 9, by: "anon" } ]
}
{
  _id: 2,
  item: "XYZ",
  ratings: [ { score: 5, by: "anon" }, { score: 7, by: "wv" } ]
}

创建索引:
db.survey2.createIndex( { "ratings.score": 1, "ratings.by": 1 } )

查询语句:
db.survey2.find( { ratings: { $elemMatch: { score: { $lte: 5 }, by: "anon" } } } )
逐个索引分析:
score {$lte:5}的边界是:[-inf,5],
by {by:"anon"}的边界是:["anon":"anon"]
mongodb 索引混合的结果为:
{ "ratings.score" : [ [ -Infinity, 5 ] ], "ratings.by" : [ [ "anon", "anon" ] ] }

再看一个例子:
{
  _id: 1,
  item: "ABC",
  ratings: [
    { score: { q1: 2, q2: 5 }, certainty: { q1: 2, q2: 3 } },
    { score: { q1: 8, q2: 4 }, certainty: { q1: 10, q2: 10 } }
  ]
}
{
  _id: 2,
  item: "XYZ",
  ratings: [
    { score: { q1: 7, q2: 8 }, certainty: { q1: 5, q2: 5 } },
    { score: { q1: 9, q2: 5 }, certainty: { q1: 7, q2: 7 } }
  ]
}
创建的索引为:
db.survey4.createIndex( {
   "ratings.score.q1": 1,
   "ratings.score.q2": 1,
   "ratings.certainty.q1": 1,
   "ratings.certainty.q2": 1
} )
查询的语句为:
db.survey4.find(
  {
    "ratings.score": { $elemMatch: { q1: 5, q2: 5 } },
    "ratings.certainty": { $elemMatch: { q1: 7, q2: 7 } },
  } 
但是,当$elemMatch不能连接
"ratings.score"和"ratings.certainty",mongodb 不能混合它们两个的边界,然而,mongodb 强制领导索引字段"ratings.score.q1" 和 "ratings.score.q2"的边界混合。
边界的混合结果如下:
{
  "ratings.score.q1" : [ [ 5, 5 ] ],
  "ratings.score.q2" : [ [ 5, 5 ] ],
  "ratings.certainty.q1" : [ [ MinKey, MaxKey ] ],
  "ratings.certainty.q2" : [ [ MinKey, MaxKey ] ]
}


 









 

posted @ 2016-10-18 12:20  Jensen_Lv  阅读(1938)  评论(0编辑  收藏  举报