Mongodb的通配符索引

学习mongodb,体会mongodb的每一个使用细节,欢迎阅读威赞的文章。这是威赞发布的第95篇mongodb技术文章,欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题,欢迎在文章下面点个赞,或者关注威赞。谢谢。威赞文章都是结合官方文档,翻译整理而来,并对每个知识点的描述都认真思考和实践,对难以理解的地方,使用简单容易理解的方式进行阐述。

Mongodb支持灵活的数据结构定义,同一个Collection的不同文档,可以拥有不同的字段,使用相同字段存储不同的数据类型,甚至缺少某些字段。这样灵活的数据结构,在构建索引时,应用开发人员或数据库管理员无法知道当前文档是否包含该字段,或者字段的名称是什么。Mongodb提供了通配符索引,来满足这样的应用场景。使用通配符索引,为未知字段或不确定的字段来添加索引。

概述

创建Mongodb索引时,使用通配符$**来创建通配符索引

复制代码
db.collection.createIndex({ "$**": <sortOrder>})

为嵌入式文档添加索引

复制代码
db.collection.createIndex({"<field>.$**": <sortOrder>})

只有当用户在不确定字段未来是否会变化,或不清楚需要创建索引的字段时,才使用通配符来创建索引。通配符索引和普通的确定字段索引的行为不一样。如果集合中因为随意的字段名称导致不能够创建索引,Mongodb官方建议首先统一字段名称。而不是创建通配符索引来代替普通索引。通配符索引,适用于下面几个场景

  • 系统应用查询的集合中文档字段不同,为该集合添加通配符索引,包含所有需要查询的字段
  • 针对字段不一致的嵌入式文档的查询,为该嵌入式文档创建通配符索引
  • 使用复合通配符索引,能够提高常用查询条件的索引覆盖率。

使用和限制

  • 用户可以在同一个集合当中添加多个通配符索引
  • 通配符索引字段可以包含其他索引字段
  • 默认通配符字段不包含_id字段。用户需要在wildcardProjection字段中显示指定_id字段
  • 通配符字段索引时稀疏的,只包含带有包含通配符字段的文档。即使该字段是null值,也会被包含在索引中
  • 通配符索引和通配符文本索引,不是同一个索引。通配符索引不支持使用$text进行文本查询。
  • 当符合下面所有条件时,通配符索引才能够支持索引覆盖查询
    • Mongodb选择通配符索引作为选中的索引
    • 查询过滤条件中只包含通配符索引当中的字段
    • 查询结果显示指定不包含_id字段,只包含查询字段
    • 指定的查询字段,不是数组字段

如在employees集合中添加通配符索引

复制代码
db.employees.createIndex({"$**": 1})

该索引能够覆盖查询

复制代码
db.employees.find({"last_name": "Doe"}, {"last_name": 1, "_id": 0})

查看该查询的执行计划

应用

创建集合products并插入数据

复制代码
db.products.insertMany([
    {
        product_name: "Spy Coat",
        attributes: {
            material: [ "Tweed", "Wool", "Leather" ],
            size: {
                length: 72,
                unites: "inches"
            }
        }
    }, {
        product_name: "Spy Pen",
        attributes: {
            colors: [ "Blue", "Black" ],
            secret_feature: {
                name: "laser",
                power: "1000",
                units: "watts"
            }
        }
    }
])

为字段添加通配符索引

该通配符索引支持字段attributes和attributes文档中的字段查询

复制代码
db.products.createIndex({"attributes.$**": 1})

查询文档数据

复制代码
db.products.find({"attributes.size.length": {$gt: 60}})
db.products.find({"attributes.material": "Leather"})
db.products.find({"attributes.secret_feature.name": "laser"}, {"attributes.secret_colors": 1, product_name: 1,  "_id": 0})

指定通配符索引包含的字段

Mongodb允许用户创建通配符索引时,指定包含哪些字段或不包含哪些字段。如文档中包含多个嵌入式文档,用户可以包含这些嵌入式文档和嵌入式文档中的字段。或者用户添加通配符索引时,排除不需要查询的字段。

按照下面的语法指定包含的字段,其中1表示包含,0表示不包含

vb 复制代码
`db.collection.createIndex(
  {
    "$**": <sortOrder>
  },
  {
    "wildcardProjection": {
      <field1>: <0|1>,
      <field2>: <0|1>,
      ...
      <fieldn>: <0|1>,
    }
  }
)`

指定包含哪些字段时,有下面两个限制

  • wildcardProjection只能用于通配符索引中

  • 除了_id字段外,通配符索引创建时,不能同时指定包含和排除哪些字段。如下面这样的写法,是不可用的

    {
    "wildcardProjection": {
    "attributes": 0,
    "users": 1
    }
    }

而带有_id字段时,指定包含_id字段而不包含其他字段,是可以的

复制代码
{
  "wildcardProjection": {
    "attributes": 0,
    "_id": 1
  }
}

在products集合添加索引,包含attributes文档中的size和color字段

复制代码
db.products.createIndex({
    "$**": 1
}, {
    wildcardProjection: {
        "attributes.colors": 1,
        "attributes.size": 1
    }  
}) 

在products集合添加索引,不包含attributes文档中的memory字段

复制代码
db.products.createIndex({
    "$**": 1
}, {
    wildcardProjection: {
        "attributes.memory": 0
    }  
}) 

在集合的所有字段上添加索引

添加集合artwork并插入数据

复制代码
db.artWork.insertMany([
    {
        title: "The Scream",
        artist: "Edvard Munch",
        year: 1893,
        medium: "oil on canvas",
        dimensions: {
            height: 91,
            width: 73
        }
    }, {
        title: "The Persistence of Memory",
        artist: "Salvador Dali",
        year: 1931,
        medium: "oil on canvas",
        dimensions: {
            height: 24,
            width: 33
        }
    }
])

为所有字段添加索引

复制代码
db.artWork.createIndex({"$**": 1})

查询数据

复制代码
db.artWork.find({"year": 1931})
db.artWork.find({"dimensions.height": {$gt: 30}})
相关推荐
java1234_小锋2 小时前
MySQL中有哪几种锁?
数据库·mysql
Charlie__ZS3 小时前
Redis-事务
数据库·redis·缓存
Charlie__ZS3 小时前
Redis-数据类型
数据库·redis·缓存
神奇小永哥3 小时前
redis之缓存击穿
数据库·redis·缓存
莳花微语4 小时前
记录一次因ASM磁盘组空间不足,导致MAP进程无法启动
数据库·oracle
红云梦5 小时前
互联网三高-数据库高并发之分库分表
数据库·高并发·三高架构
王军新5 小时前
MySQL索引介绍
数据库·mysql
努力奋斗的小杨5 小时前
学习MySQL的第八天
数据库·笔记·学习·mysql·navicat
橘猫云计算机设计6 小时前
基于Python电影数据的实时分析可视化系统(源码+lw+部署文档+讲解),源码可白嫖!
数据库·后端·python·信息可视化·小程序·毕业设计
Another Iso6 小时前
MySQL 事务的优先级
数据库·mysql