首先说一下 $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) 由于上面的查询条件可以求交集,但是,假如还有一种情况,有两个数组:

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

{ _id: 2, results: [ 75, 88, 89 ] ,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 ] ]
}






mongodb 中的Multikey Index Bounds解释$elemMatch的更多相关文章

  1. Spring中映射Mongodb中注解的解释

    spring-data-mongodb中的实体映射是通过MongoMappingConverter这个类实现的.它可以通过注释把java类转换为mongodb的文档. 它有以下几种注释: @Id - ...

  2. Mongodb中Sharding集群

    随着mongodb数据量的增多,可能会达到单个节点的存储能力限制,以及application较大的访问量也会导致单个节点无法承担,所以此时需要构建集群环境,并通过sharding方案将整个数据集拆分成 ...

  3. 使用aggregate在MongoDB中查找重复的数据记录

    我们知道,MongoDB属于文档型数据库,其存储的文档类型都是JSON对象.正是由于这一特性,我们在Node.js中会经常使用MongoDB进行数据的存取.但由于Node.js是异步执行的,这就导致我 ...

  4. spring data mongodb中,如果对象中的属性不想加入到数据库字段中

    spring data mongodb中,如果对象中的属性不想加入到数据库字段中,可加@Transient注解,声明为透明属性 spring data mongodb 官网帮助文档 http://ww ...

  5. 分析AJAX抓取今日头条的街拍美图并把信息存入mongodb中

    今天学习分析ajax 请求,现把学得记录, 把我们在今日头条搜索街拍美图的时候,今日头条会发起ajax请求去请求图片,所以我们在网页源码中不能找到图片的url,但是今日头条网页中有一个json 文件, ...

  6. Mongodb中 Documents文档说明

    mongodb使用BSON格式存储数据记录. 如下图: 文档结构 文档有键值对组成, 有以下结构: {    field1: value1,    field2: value2,    ...     ...

  7. MongoDB中的explain和hint提的使用

    一.简介 这里简单介绍一下各个工具的使用场景,一般用mysql,redis,mongodb做存储层,hadoop,spark做大数据分析. mysql适合结构化数据,类似excel表格一样定义严格的数 ...

  8. 在MongoDB中执行查询、创建索引

    1. MongoDB中数据查询的方法 (1)find函数的使用: (2)条件操作符: (3)distinct找出给定键所有不同的值: (4)group分组: (5)游标: (6)存储过程. 文档查找 ...

  9. mongodb中查询返回指定字段

    mongodb中查询返回指定字段   在写vue项目调用接口获取数据的时候,比如新闻列表页我只需要显示新闻标题和发表时间,点击每条新闻进入详情页的时候才会需要摘要.新闻内容等关于此条新闻的所有字段.  ...

随机推荐

  1. 内存空间申请(C)

    标准C,C++: malloc----free new----delete WINDOWS API: gnew(.net) LocalAlloc----LocalFree GlobalAlloc--- ...

  2. JS中的加号+运算符详解

    加号+运算符 在 JavaScript 中,加法的规则其实很简单,只有两种情况: 把数字和数字相加 把字符串和字符串相加 所有其他类型的值都会被自动转换成这两种类型的值. 为了能够弄明白这种隐式转换是 ...

  3. HTML学习笔记——常用元素及其属性(一)

    1.img 标签 -- 代表HTML图像 img标签是单独出现的,<img /> 语法: <img src="URI" alt="alttext&quo ...

  4. &#x编码转换成汉字

    import java.io.UnsupportedEncodingException; public class UnicodeDecoder { public static String esca ...

  5. java内部类详细介绍

    0.内部类与一般类有所不同,它是放在外部类的内部即可作为外部类的成员变量,也可放在方法内部作为局部变量,既然是变量,那么它可以用 private static 修饰符修饰,而外部类则不能,这也是内部类 ...

  6. springboot之修改内置tomcat配置项

    1.spring boot默认端口号是8080,如果要修改端口的话,只需要修改application.properties文件,在其中加入 例如: server.port=8081 2.在正常的项目中 ...

  7. OC中nil、Nil、NULL、NSNull的区别

    nil:指向OC中对象的空指针 e.g.: NSString *string = nil; Nil:指向OC中类的空指针    e.g.:Class class = Nil; NULL:指向其他类型的 ...

  8. iOS 横竖屏适配

    关于横竖屏适配 也没做过,今天读别人的源码,遇到了.为了了解清楚,就系统的学习一下. 一 横竖屏方向枚举 关于横竖屏一共有三种枚举 UIInterfaceOrientation UIInterface ...

  9. js获取链接等号“=”后面的参数

    用该属性获取页面 URL 地址: window.location 对象所包含的属性 属性 描述 hash 从井号 (#) 开始的 URL(锚) host 主机名和当前 URL 的端口号 hostnam ...

  10. RabbitMQ_消息队列基本使用_1

    什么叫消息队列 消息(Message)是指在应用间传送的数据.消息可以非常简单,比如只包含文本字符串,也可以更复杂,可能包含嵌入对象. 消息队列(Message Queue)是一种应用间的通信方式,消 ...