服务器之家:专注于服务器技术及软件下载分享
分类导航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|数据库技术|

服务器之家 - 数据库 - MongoDB - MongoDB通配符索引的用法实例

MongoDB通配符索引的用法实例

2020-09-12 18:44DBA团队 MongoDB

这篇文章主要给大家介绍了关于MongoDB通配符索引的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

指南

MongoDB在4.2 版本推出了Wildcard Indexes,究竟什么是Wildcard Indexes以及Wildcard Indexes适合哪些场景本文结合官方文档以及实际测试进行简单概述。

1、通配符索引示例

因为MongoDB是dynamic schemas,所以应用是可以查询任何已知字段或者随机字段的。

假设(此假设案例摘自官方文档),集合colA的UserMetadata字段包含如下数据:

?
1
2
3
4
{ "userMetadata" : { "likes" : [ "dogs", "cats" ] } }
{ "userMetadata" : { "dislikes" : "pickles" } }
{ "userMetadata" : { "age" : 45 } }
{ "userMetadata" : "inactive" }

但是在查询的时候可能是如下语句:

?
1
2
3
4
5
db.colA.find({ "userMeta2
通配符索引的形式data.likes" : "dogs" })
db.colA.find({ "userMetadata.dislikes" : "pickles" })
db.colA.find({ "userMetadata.age" : { $gt : 30 } })
db.colA.find({ "userMetadata" : "inactive" })

是否能通过一个索引来完成上述需求?

答案是肯定的,上述查询可以通过通配符索引来实现既定需求,也就是 db.colA.createIndex( { "userMetadata.$**" : 1 } )。

那么如何创建通配符索引?

注意:首先应该明确的是通配符索引只在版本兼容性4.2的时候才能创建。

如何查询版本兼容性?

?
1
db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )

如何设置?

?
1
db.adminCommand( { setFeatureCompatibilityVersion: "4.2" } )

2、通配符索引的形式

单字段通配符索引

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
 "_id" : ObjectId("5ee2df16911d8dfaa91520b4"),
 "product_name" : "Spy Coat",
 "product_attributes" : {
 "material" : [
 "Tweed",
 "Wool",
 "Leather"
 ],
 "size" : {
 "length" : 72,
 "units" : "inches"
 }
 }
}
{
 "_id" : ObjectId("5ee2df30911d8dfaa91520b5"),
 "product_name" : "Spy Pen",
 "product_attributes" : {
 "colors" : [
 "Blue",
 "Black"
 ],
 "secret_feature" : {
 "name" : "laser",
 "power" : "1000",
 "units" : "watts"
 }
 }
}

如果数据结构是上面这样的,其中product_attributes 属性包含任何的结构。

那么如果我们创建一个这个索引,它会进行什么操作?

db.product_catalog.createIndex({"product_attributes.$**":1})。

因为product_attributes 里面包含数组和嵌套文档等对象,实际创建这个索引后,会迭代嵌套文档或者数组把里面的所有的值都取出来放到索引里。支持如下查询:

?
1
2
3
db.product_catalog.find({"product_attributes.colors":"Blue"})
db.product_catalog.find({"product_attributes.secret_feature.name":"laser"})
db.product_catalog.find({"product_attributes.size.length":{$gt:60}})

全字段的通配符索引

可以通过下面的语句创建一个索引,索引中包含集合中的所有字段,但是不包括_id(如果想包含_id可以通过wildcardProjection 来设置),如果集合中的字段包含数组或者嵌套对象的话,那么会迭代数组或者嵌套对象并把值放到索引中。

?
1
Db.product_catalog.createIndex({“$**”:1})

给每个文档添加一个address的字段。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
7777:PRIMARY> db.product_catalog.find().pretty()
{
 "_id" : ObjectId("5ee2df16911d8dfaa91520b4"),
 "product_name" : "Spy Coat",
 "product_attributes" : {
 "material" : [
 "Tweed",
 "Wool",
 "Leather"
 ],
 "size" : {
 "length" : 72,
 "units" : "inches"
 }
 },
 "address" : "Beijing"
}
{
 "_id" : ObjectId("5ee2df30911d8dfaa91520b5"),
 "product_name" : "Spy Pen",
 "product_attributes" : {
 "colors" : [
 "Blue",
 "Black"
 ],
 "secret_feature" : {
 "name" : "laser",
 "power" : "1000",
 "units" : "watts"
 }
 },
 "address" : "Tianjin"
}
 
db.product_catalog.find({"product_name":"Spy Coat","address":"nanji","product_attributes.colors":"Blue"})

在全字段通配符索引的基础上可以明确包含哪些或者不包含哪些字段到通配符索引中,只能是在全字段通配符索引的基础上,单字段的是不可以的:

在全字段的基础上创建一个明确包含哪些字段的索引:

?
1
2
3
4
5
6
db.collection.createIndex(
 { "$**" : 1 },
 { "wildcardProjection" :
 { "fieldA" : 1, "fieldB.fieldC" : 1 }
 }
)

注意:通配符索引不支持在使用wildcardProjection的时候混合使用包含和排除语句,除了明确指定包含_id字段的时候。

在全字段的基础上创建一个明确不包含哪些字段的索引:

?
1
2
3
4
5
6
db.collection.createIndex(
 { "$**" : 1 },
 { "wildcardProjection" :
 { "fieldA" : 0, "fieldB.fieldC" : 0 }
 }
)

3、通配符索引的行为

通配符索引的行为根据其字段类型不同而有所不同。

  • 字段为对象
    如果是对象的话,会将对象中的内容存储到索引中,通配符索引会把对象中的所有嵌套对象加载到索引中。
  • 字段为数组
    如果是数组的话,通配符索引遍历数组并且将每个元素都存储到索引中。
    如果数组中的元素是一个对象的话,通配符索引把对象中的内容加载到索引中,像上面的加载对象一样。
    如果数组中的元素是一个数组的话(就是多维数组),通配符索引并不迭代嵌套数组,相反是把整个嵌套数组作为一个值来看。
  • 其他类型
    把值记录到数组中。
    通配符索引会持续迭代任何的嵌套对象或者数组直到最底层(就是不能在迭代为止),然后它会索引全路径。

通配符索引对于显示数组位置的查询

通配符索引虽然不会记录给定数组中的元素下标,但是,MongoDB仍然可以选择通配符索引来满足包含一个或多个显式数组索引的字段路径的查询(for example, parentArray.0.nestedArray.0)

由于为每个连续嵌套数组定义索引边界的复杂性日益增加,如果该路径包含8个以上的显式数组索引,MongoDB不会考虑使用通配符索引来回答查询中的给定字段路径。MongoDB仍然可以考虑使用通配符索引来回答查询中的其他字段路径。

如果超过了8个以上显示数组索引的话MongoDB 会考虑另外的索引或者执行全集合扫描。如下结构:

?
1
2
3
4
5
6
7
8
9
10
{
 "parentObject" : {
 "nestedArray" : [
 "elementOne",
 {
  "deeplyNestedArray" : [ "elementTwo" ]
 }
 ]
 }
}

请注意,通配符索引本身对索引文档时遍历文档的深度没有任何限制;该限制仅适用于显式指定精确数组索引的查询。通过发出没有显式数组索引的相同查询,MongoDB可以选择通配符索引来回答查询。

4、通配符索引的限制

1.首先通配符索引是一个稀疏索引,只存放存在的字段在索引里面,不存在的不存放,也就是说当你使用{$exists:false}的时候,是不会走索引的,是全集合扫描。

db.test_new_wildidx.find({"block.attr":{$exists:false}})

db.test_new_wildidx.find({"block.attr":{$exists:true}})  但是支持true的。

2.通配符索引不支持直接等于/不等于一个对象或者数组。

通配符索引会将对象或者数组中的元素加载到索引中,而不是整体放到索引中。故通配符索引不支持直接用文档或者数组来匹配。

所以上面的例子如果

?
1
7777:PRIMARY> db.test_new_wildidx.find({"block.attr.address_new": ["haicheng", "beijing", "chongqing"]})

就是想匹配整个数组的话,是不可能用到通配符索引的。

那么如果有这个需求该如何解决?Db.test_new_wildidx.createIndex({"block.attr.address_new":1}) 通过这个索引来解决。

虽然通配符索引不支持整个文档或者对象直接精准匹配查询,但是支持数组或者对象为空{} 这种操作:

?
1
2
7777:PRIMARY> db.test_new_wildidx.find({"block.attr": {}})
7777:PRIMARY> db.test_new_wildidx.find({"block.attr.address_new": {}})

3. 通配符索引支持如下索引类型或者或者属性:

Compound
TTL
Text
2d (Geospatial)
2dsphere (Geospatial)
Hashed
Unique

4.通配符索引不支持文档中的数组$ne null这种。其实不光是数组,别的字段也同样,只要是$ne都不会使用通配符索引。

5、总结

通配符索引在一定程度上可以应对在建模初期对于索引建立疏忽的遗漏,但是如果一味依赖通配符索引来解决查询中的各种精确字段的匹配那就是郑人买履了,在实际测试中通配符索引和精确字段的索引相比随着数据的增长效率逐渐下滑。这也是官方不是很建议使用通配符索引来替代常规索引的原因。

到此这篇关于MongoDB通配符索引的文章就介绍到这了,更多相关MongoDB通配符索引内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://mp.weixin.qq.com/s/Yoh20RSNQMvvjOeS-p_66A

延伸 · 阅读

精彩推荐
  • MongoDBMongodb实现定时备份与恢复的方法教程

    Mongodb实现定时备份与恢复的方法教程

    这篇文章主要给大家介绍了Mongodb实现定时备份与恢复的方法教程,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面...

    chenjsh364522020-05-13
  • MongoDB分布式文档存储数据库之MongoDB分片集群的问题

    分布式文档存储数据库之MongoDB分片集群的问题

    这篇文章主要介绍了分布式文档存储数据库之MongoDB分片集群的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋...

    Linux-18743072020-12-20
  • MongoDBmongodb基本命令实例小结

    mongodb基本命令实例小结

    这篇文章主要介绍了mongodb基本命令,结合实例形式总结分析了MongoDB数据库切换、查看、删除、查询等基本命令用法与操作注意事项,需要的朋友可以参考下...

    dawn-liu3652020-05-26
  • MongoDBMongoDB中javascript脚本编程简介和入门实例

    MongoDB中javascript脚本编程简介和入门实例

    作为一个数据库,MongoDB有一个很大的优势——它使用js管理数据库,所以也能够使用js脚本进行复杂的管理——这种方法非常灵活 ...

    MongoDB教程网6982020-04-24
  • MongoDB迁移sqlserver数据到MongoDb的方法

    迁移sqlserver数据到MongoDb的方法

    这篇文章主要介绍了迁移sqlserver数据到MongoDb的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    听枫xl9682021-01-03
  • MongoDBMongoDB安装图文教程

    MongoDB安装图文教程

    这篇文章主要为大家详细介绍了MongoDB安装图文教程,分为两大部分为大家介绍下载MongoDB和安装MongoDB的方法,感兴趣的小伙伴们可以参考一下 ...

    Yangyi.He6132020-05-07
  • MongoDBMongoDB 内存使用情况分析

    MongoDB 内存使用情况分析

    都说 MongoDB 是个内存大户,但是怎么知道它到底用了多少内存呢...

    MongoDB教程网10002020-09-29
  • MongoDBMongoDB凭什么跻身数据库排行前五

    MongoDB凭什么跻身数据库排行前五

    MongoDB以比去年同期超出65.96分的成绩继续雄踞榜单前五,这个增幅在全榜仅次于PostgreSQL的77.99,而其相对于4月份的6.10分的增长也是仅次于微软SQL Server排名...

    孙浩峰3892020-05-22