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}})
相关推荐
Think Spatial 空间思维7 分钟前
【HTTPS基础概念与原理】TLS握手过程详解
数据库·网络协议·https
laowangpython26 分钟前
MySQL基础面试通关秘籍(附高频考点解析)
数据库·mysql·其他·面试
mooyuan天天1 小时前
SQL注入报错“Illegal mix of collations for operation ‘UNION‘”解决办法
数据库·web安全·sql注入·dvwa靶场·sql报错
运维-大白同学1 小时前
go-数据库基本操作
开发语言·数据库·golang
R-sz1 小时前
通过从数据库加载MinIO配置并初始化MinioClient,spring boot之Minio上传
数据库·oracle
洛阳泰山1 小时前
Windows系统部署MongoDB数据库图文教程
数据库·windows·mongodb
医只鸡腿子2 小时前
3.2/Q2,Charls最新文章解读
数据库·数据挖掘·数据分析·深度优先·数据库开发
bang___bang_2 小时前
PostgreSQL内幕剖析——结构与架构
数据库·postgresql
龙俊亨3 小时前
达梦数据库查看各数据库表内容
数据库
·云扬·4 小时前
【PmHub后端篇】PmHub 中缓存与数据库一致性的实现方案及分析
数据库·缓存