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) 由于上面的查询条件可以求交集,但是,假如还有一种情况,有两个数组:
{ _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的更多相关文章
- Spring中映射Mongodb中注解的解释
spring-data-mongodb中的实体映射是通过MongoMappingConverter这个类实现的.它可以通过注释把java类转换为mongodb的文档. 它有以下几种注释: @Id - ...
- Mongodb中Sharding集群
随着mongodb数据量的增多,可能会达到单个节点的存储能力限制,以及application较大的访问量也会导致单个节点无法承担,所以此时需要构建集群环境,并通过sharding方案将整个数据集拆分成 ...
- 使用aggregate在MongoDB中查找重复的数据记录
我们知道,MongoDB属于文档型数据库,其存储的文档类型都是JSON对象.正是由于这一特性,我们在Node.js中会经常使用MongoDB进行数据的存取.但由于Node.js是异步执行的,这就导致我 ...
- spring data mongodb中,如果对象中的属性不想加入到数据库字段中
spring data mongodb中,如果对象中的属性不想加入到数据库字段中,可加@Transient注解,声明为透明属性 spring data mongodb 官网帮助文档 http://ww ...
- 分析AJAX抓取今日头条的街拍美图并把信息存入mongodb中
今天学习分析ajax 请求,现把学得记录, 把我们在今日头条搜索街拍美图的时候,今日头条会发起ajax请求去请求图片,所以我们在网页源码中不能找到图片的url,但是今日头条网页中有一个json 文件, ...
- Mongodb中 Documents文档说明
mongodb使用BSON格式存储数据记录. 如下图: 文档结构 文档有键值对组成, 有以下结构: { field1: value1, field2: value2, ... ...
- MongoDB中的explain和hint提的使用
一.简介 这里简单介绍一下各个工具的使用场景,一般用mysql,redis,mongodb做存储层,hadoop,spark做大数据分析. mysql适合结构化数据,类似excel表格一样定义严格的数 ...
- 在MongoDB中执行查询、创建索引
1. MongoDB中数据查询的方法 (1)find函数的使用: (2)条件操作符: (3)distinct找出给定键所有不同的值: (4)group分组: (5)游标: (6)存储过程. 文档查找 ...
- mongodb中查询返回指定字段
mongodb中查询返回指定字段 在写vue项目调用接口获取数据的时候,比如新闻列表页我只需要显示新闻标题和发表时间,点击每条新闻进入详情页的时候才会需要摘要.新闻内容等关于此条新闻的所有字段. ...
随机推荐
- android EditText 限定中文个数与英文个数的解决方式
EditText 限定中文8个英文16个的解决方法. 在EditText上控件提供的属性中有限定最大最小长度的方法. 可是,对于输入时,限定中文8个英文16个时,怎么办?相当于一个中文的长度是两个英文 ...
- Java中将时间戳转化为Date类型
时间戳timestamp,从前端接收到后.他能够是一个long或者包装类Long再或者是个String类型.仅仅需 new Date(时间戳) 就能够直接转化为java.util.Date类型. 转化 ...
- CFindReplaceDialog学习
The CFindReplaceDialog class allows you to implement standard string Find/Replace dialog boxes in yo ...
- package-cleanup用法
今天升级时候遇到"you could try using package-cleanup --problems to work around the problem ...", 本 ...
- modelform 对象和model之间的关系
一.modelform的每一个标签对象 for bound_field in form: print('form.model',form.Meta.model) ...
- Jmeter BeanShell 引用变量报错jmeter.util.BeanShellInterpreter: Error invoking bsh method: eval Parse error at line 14, column 181 : Error or number too big for integer
如果你通过CSV Data Set Config或者_StringFromFile函数来参数化你的请求,需要特别注意当参数为纯数字时,jmeter会默认将其识别成int型数据,说明jmeter并不是默 ...
- python学习【第五篇】python函数 (二)
一.装饰器 装饰器:本质就是函数,功能是为其它函数添加附加功能 装饰器的原则: 不修改被修饰函数的源代码 不修改被修饰函数的调用方式 装饰器的知识储备: 装饰器 = 高阶函数 + 函数嵌套 + 闭包 ...
- python学习【第二篇】初识python
python的安装 windows 1.下载安装包 https://www.python.org/downloads/ 2.安装 默认安装路径:C:\python27 3.配置环境变量 [右键计算机] ...
- asp.net分页功能的实现
效果图: 代码:static int PageSize = 30; #region 分页部分代码 //*********************************** 数据分页 ******** ...
- 使用MyBatis_Generator工具jar包自动化生成Dto、Dao、Mapping 文件
由于MyBatis属于一种半自动的ORM框架,所以主要的工作将是书写Mapping映射文件,但是由于手写映射文件很容易出错,所以查资料发现有现成的工具可以自动生成底层模型类.Dao接口类甚至Mappi ...