学习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}})