MongoDB 索引(第 13 天)

作者 : 慕源网 本文共9014个字,预计阅读时间需要23分钟 发布时间: 2021-11-2 共478人阅读

在阅读本文之前,我强烈建议您阅读本系列的前几期:

简介

索引支持查询的高效解析。索引以有效的方式执行查询。在没有索引的情况下,MongoDB 会执行集合扫描。在集合扫描中,MongoDB 单独扫描每个文档以选择那些符合选择标准的文档。这种方法需要大量的时间和资源。因此 MongoDB 提供了索引,可以提供一种可靠且高效的扫描文档的方式。如果查询存在合适的索引,那么 MongoDB 可以使用此索引来限制它必须扫描的文档数量。

索引是一种特殊的数据结构,它以易于遍历的形式存储一小部分数据集。索引可以存储特定字段或一组字段的值,按索引中指定的字段值排序。

索引类型

MongoDB 支持多种类型的索引。我们可以在单个字段、多个字段、嵌入字段的索引或嵌入文档的索引上创建索引。我们应该为查询中经常使用的字段创建一个索引,这样我们就可以确保 MongoDB 扫描尽可能少的文档。createIndex() 方法创建索引。

MongoDB 具有以下类型的索引。

  • 默认索引
  • 单字段索引
  • 复合指数
  • 多键索引
  • 文本索引
  • 地理空间索引
  • 哈希索引

现在简单介绍一下每种类型的索引。

Default _ID

每个 MongoDB 集合都在集合的 _id 字段上包含一个内置索引。这是 MongoDB 使用的默认索引。_id 字段的索引包含 Unique 属性。换句话说,我们不能在 _id 字段中插入重复值。如果我们没有为 _id 字段指定值,那么 MongoDb 会自动在 _id 字段中插入一个唯一值。_id 字段的索引按升序存储数据。

示例

db.post.find({},{_id:1,Likes:1}).pretty()

{ "_id" : ObjectId("55c545e1acae58b1a7d7dff1"), "Likes" : 5 }  
{ "_id" : ObjectId("55c54617acae58b1a7d7dff2"), "Likes" : 4 }  
{ "_id" : ObjectId("55c54665acae58b1a7d7dff3"), "Likes" : 4 }  
{ "_id" : ObjectId("55c546a6acae58b1a7d7dff4"), "Likes" : 5 }  
{ "_id" : ObjectId("55c546d9acae58b1a7d7dff5"), "Likes" : 3 }  
{ "_id" : ObjectId("55c54711acae58b1a7d7dff6"), "Likes" : 6 }  

在前面的示例中,我们检索 _id,就像“post”集合中的字段一样。前面输出中的 _id 按升序排列。

单字段索引

在 MongoDB 中,我们可以为单个字段或多个字段创建索引。要在单个字段上创建索引,请使用排序顺序选项传递该字段的名称。

语法

db.Collection_Name.createIndex({field:sorting_order})

Sorting_Order

1 表示升序排序,-1 表示降序排序。

示例

db.post.createIndex({Likes:1})

输出

{  
    "createdCollectionAutomatically": false,  
    "numIndexesBefore": 1,  
    "numIndexesAfter": 2,  
    "ok": 1  
}  

在前面的示例中,我们在“Likes”字段上创建了一个索引,并将排序顺序指定为 1。换句话说,索引按升序对项目进行排序。我们可以看到 createIndex() 方法在确认中返回 4 个参数。第一个参数是“createdCollectionAutomatically”,它指定该索引是用户定义的还是由集合自动创建的。第二个参数是“numIndexesBefore”,它指定了当前命令执行前的索引数。第三个参数是“numIndexesAfter”,它定义了当前命令执行后的索引数。第四个参数是“ok”,表示创建索引,1表示成功,0表示失败。

嵌入字段索引

在前面的示例中,我们为顶级字段创建了一个索引,以便我们可以为嵌入文档的字段创建一个索引。使用“点符号”在嵌入字段上创建索引。

例子

{  
    "_id": ObjectId("55c545e1acae58b1a7d7dff1"),  
    "PostBY": "Pankaj choudhary",  
    "Time": ISODate("2015-08-07T23:57:21.041Z"),  
    "Title": "Introduction of MongoDB",  
    "Tags": [  
        "NoSQL",  
        "MongoDB",  
        "Database"],  
    "Likes": 5,  
    "Comment": {  
        "CommentBy": "Rahul",  
        "Text": "Nice Article"  
    }  
  
}  

现在我们使用以下规范在嵌入文档的“CommentBy”字段上创建索引。

db.post.createIndex({“Comment.CommentBy”:1})

嵌入文档的索引 在

前面的例子中,我们为嵌入的字段创建了一个索引。现在我们为嵌入的文档创建一个索引。

例如,post-collection 包含作为嵌入文档的“Comment”字段。

示例

db.post.createIndex({“Comment”:1})

复合索引

在 MongoDB 中,我们可以为集合的多个字段创建索引。MongoDB 在单个复合索引中支持 31 个字段。

下面是一个例子:

{  
    "_id": ObjectId("55c545e1acae58b1a7d7dff1"),  
    "PostBY": "Pankaj choudhary",  
    "Time": ISODate("2015-08-07T23:57:21.041Z"),  
    "Title": "Introduction of MongoDB",  
    "Tags": [  
        "NoSQL",  
        "MongoDB",  
        "Database"],  
    "Likes": 5,  
    "Comment": {  
        "CommentBy": "Rahul",  
        "Text": "Nice Article"  
    }  
  
}  
{  
    "_id": ObjectId("55c545e1acae58b1a7d7dff1"),  
    "PostBY": "Pankaj choudhary",  
    "Time": ISODate("2015-08-07T23:57:21.041Z"),  
    "Title": "Introduction of MongoDB",  
    "Tags": [  
        "NoSQL",  
        "MongoDB",  
        "Database"],  
    "Likes": 5,  
    "Comment": {  
        "CommentBy": "Rahul",  
        "Text": "Nice Article"  
    }  
  
}  

现在我们按照以下排序顺序创建两个字段的复合索引。

db.post.createIndex({“Comment”:1,Title:-1})

前面的查询对排序进行索引,首先按“Comment”字段升序,然后按“Title”字段降序排列。

前缀

索引前缀是指索引字段的开始子集。我们来看一个例子:

db.post.createIndex({Comment:1,Title:-1,PostBy:1})

上面的索引有以下索引前缀:

  • { Comment:1}
  • {Comment:1,Title:-1}

MongoDB 对包含以下字段的查询使用前面的索引。

  • Comment 字段
  • Comment 和 Title 字段
  • Comment 和 Title 以及 PostBY 字段

MongoDB 从不将前面的索引用于包含以下字段的查询。

  • Title 字段
  • PostBY 字段
  • Title 和 PostBY 字段

MongoDB 可以将前面的索引用于包含“Comment”和“PostBY”字段的查询,因为“Comment”字段对应于一个前缀。但是这个索引不会像“Comment”和“PostBY”字段的单独索引那样有效。

多键索引

如果我们在保存数组值的字段上创建索引,那么 MongoDB 会为数组中的每个元素创建一个索引键。多键索引支持对数组字段的高效查询。可以在包含标量值(即字符串或整数)或嵌套文档的数组字段上创建多键索引。如果索引字段是数组类型,MongoDB 会自动创建多键索引。我们不需要指定多键类型。

让我们看一个例子:

{  
    "_id": ObjectId("55c54711acae58b1a7d7dff6"),  
    "PostBY": "Pankaj choudhary",  
    "Time": ISODate("2015-08-08T00:02:25.968Z"),  
    "Title": "MongoDB Day3",  
    "Tags": [  
        "NoSQL",  
        "MongoDB",  
        "Database"],  
    "Likes": 6,  
    "Comment": [{  
        "CommentBy": "Neeraj",  
        "Text": " Nice One"  
    }, {  
        "CommentBy": "Rahul",  
        "Text": "Thanks to Share"  
    }]  
}  

在前面的文档中,我们有两个数组类型的字段。第一个是包含标量值的“Tags”,第二个是包含嵌套文档的“Comment”。现在我们为两个字段创建一个索引。

“Tags”字段的索引。
db.post.createIndex({“Tags”:-1})

“Comment”字段的索引。
db.post.createIndex({“Comment”:1})

复合多键索引

在前面的示例中,我们创建了两个索引,一个用于“Tags”字段,另一个用于“Comment”字段。但是如果多个字段是“Array”类型,我们就不能创建复合索引。

让我们尝试为“Tags”和“Comment”字段创建复合索引。

db.post.createIndex({“Comment”:-1,”Tags”:1 })

输出

{  
    "createdCollectionAutomatically": false,  
    "numIndexesBefore": 10,  
    "errmsg": "exception: cannot index parallel arrays [Tags] [Comment]",  
    "code": 10088,  
    "ok": 0  
}  

如果我们执行前面的查询,MongoDB 会抛出错误,因为 MongoDB 不允许为多个“Array”字段创建复合索引。

但是如果最多一个字段是“Array”类型,我们可以创建一个复合索引。

db.post.createIndex({“Comment”:-1,”Title”:1 })

文本索引

MongoDB 提供了“文本索引”功能来搜索集合文档中的字符串内容。文本索引可以包含任何具有字符串或字符串数​​组的字段。一个集合最多可以有一个文本索引。但是我们可以为文本索引指定多个字段。

要创建文本索引字段,请在 createIndex() 方法中将“comments”参数的值设置为“text”。

语法

db.Collection_Name.createIndex({comments:”text”})

Example1

 

db.post.createIndex({"Title":1 },{comments:"text"})

Example2

 

db.post.createIndex({"Title":1,PostBY:1},{comments:"text"})

通配符文本索引

我们知道 MongoDB 数据库由非结构化数据组成,因此有时很难预测哪些字段包含文本类型数据。MongoDB 提供通配符说明符 ($**) 以允许对具有字符串内容的所有字段进行文本搜索。使用通配符索引 MongoDB 索引所有包含字符串或文本类型数据的字段。

让我们看一个示例:

 

db.post.createIndex( { "$**": "text" } )

前面的示例使用通配符说明符创建文本索引。

我们可以在复合索引中创建通配符文本索引。让我们看一个例子。

 

db.post.createIndex({"Title":1,"$**":"text"})

在前面的例子中,我们创建了一个复合索引。此复合索引包含“Title”字段和通配符文本索引。

地理空间索引

地理空间索引主要用于存储位置数据或地理空间信息。在存储任何数据之前,我们必须确定表面的类型。MongoDB 支持两种类型的表面。

  1. Spherical

    计算球面(如地球)上的几何图形,并使用 2dsphare 在球面上存储位置数据。
  2. Flat使用 2d 索引计算欧几里得上的距离并将位置存储为旧坐标对。

散列索引

散列索引条目保持与索引字段的值的哈希值。散列函数折叠嵌入的文档并计算整个值的散列。哈希索引支持等式查询,但不支持范围查询和多键索引。我们无法为散列索引创建复合索引。但是,我们可以在同一字段上创建非哈希索引(例如单个字段或复合索引)和哈希索引。

语法

db.Collection_Name.createIndex({Field:”hashed”})

让我们看一个例子:

 

db.post.createIndex({"Title":"hashed"})

在前面的查询中,我们在“Title”字段。

索引属性

MongoDB 中的索引支持这三个索引属性。

  • 唯一索引
  • TTL索引
  • 稀疏索引

唯一索引

唯一索引属性用于限制索引字段具有重复值或已存在的所有文档。要创建唯一索引,请在 createIndex 方法中将“Unique”参数的值设置为“true”。默认情况下,唯一值是 false。

语法

db.Collection_Name.createIndex({fieldname:sorting_order},{unique:true})

示例

考虑以下“演示”集合。“Demo”集合的 Id 字段具有以下值。

db.My_Collection.find({},{_id:0})

 

{ "Id" : "1" }  
{ "Id" : "2" }  
{ "Id" : "3" }  

现在我们在“Id”字段上创建一个唯一索引。

db.Demo.createIndex({“Id”:1},{unique:true})

现在我们尝试在“Id”字段中插入一个重复值。

db.Demo.insert({Id:”1″})

输出

 

WriteResult
({  
         "nInserted" : 0,  
         "writeError" : 
         {  
                 "code" : 11000,  
                 "errmsg" : "E11000 duplicate key error index: Temp.Demo.$Id_1 dup key: { : \"1\  " }"  
         }  
 })  

此输出显示,如果我们尝试在“Unique”字段中插入重复值,那么 MongoDB 将抛出错误。

TTL 索引

TTL 索引是特殊类型的索引,MongoDB 使用它在特定时间段后自动从集合中删除文档。这种方法对于机器生成数据、日志、会话信息或临时存储信息非常有用。要创建 TTL 索引,请将 expireAfterSeconds 选项与 createIndex 方法结合使用。在 expireAfterSeconds 选项中,我们以秒为单位提供时间段。TTL 索引不保证过期数据会在过期后立即删除。文档过期时间和 MongoDB 从数据库中删除文档的时间之间可能存在延迟。

语法

 

db.Collection_Name.createIndex({fieldname:sorting_order},{ expireAfterSeconds:time})

示例

Demo 集合包含以下文档。

 

{  
    "Id": 1,  
    "Name": "Pankaj"  
} {  
    "Id": 2,  
    "Name": "Rahul"  
} {  
    "Id": 3,  
    "Name": "Sandeep"  
}  

现在我们使用 expireAfterSeconds 选项在“Id”字段上创建一个索引。

 

db.Demo.createIndex({Name:1},{expireAfterSeconds:120 })

在前面的示例中,我们创建了一个索引并将expireAfterSeconds 的值设置为120。也就是说,MongoDB 在120 秒后删除文档。

稀疏索引

稀疏索引中的的稀疏选项确保索引只包含具有索引字段的文档的条目。它还删除包含空值的文档。非稀疏索引包含所有文档,即使文档不包含索引字段。索引是“sparse”,因为它不包括集合的所有文档。

语法

db.Collection_Name.createIndex({fieldname:sorting_order}, { sparse: true })

示例

Demo 集合具有以下文档。

 

{  
    "Id": 1,  
    "Name": "Pankaj"  
} {  
    "Id": 2,  
    "Name": "Rahul"  
} {  
    "Id": 3,  
    "Name": "Sandeep"  
}  

现在我们使用稀疏选项在“Id”字段上创建一个索引。

 

db.Demo.createIndex({Name:1},{sparse:true })

在前面的示例中,我们创建了一个索引并将 sparse 选项的值设置为 true。

基本索引方法

现在我们考虑一些基本索引方法。

getIndexes() 方法

getIndexes() 方法检索集合中的所有现有索引。

语法

 

db.Collection_Name.getIndexes()

示例

 

db.Demo.getIndexes()

输出

 

[{  
    "v": 1,  
    "key": {  
        "_id": 1  
    },  
    "name": "_id_",  
    "ns": "Temp.Demo"  
}, {  
    "v": 1,  
    "key": {  
        "Id": 1  
    },  
    "name": "Id_1",  
    "ns": "Temp.Demo",  
    "expireAfterSeconds": 1200  
}, {  
    "v": 1,  
    "key": {  
        "Name": 1  
    },  
    "name": "Name_1",  
    "ns": "Temp.Demo",  
    "expireAfterSeconds": 12  
}]  

dropIndex() 方法

dropIndex() 方法从集合中删除特定索引。

语法

 

db.Collection_Name.dropIndex({Field_Name})

例子

 

db.Demo.dropIndex({"Id":1})

输出

{ "nIndexesWas" : 3, "ok" : 1 }

在前面的输出中,“nIndexesWas”反映了删除此索引之前的索引数和命令的“ok”执行状态。

ensureIndex() 方法

ensureIndex() 方法创建索引。如果相同规范的索引不存在,则 ensureIndex() 方法仅创建索引。

语法

db.Collection_Name.ensureIndex({field_name:sorting_order})

示例

db.Demo.ensureIndex({“Id”:1})

reIndex() 方法

reIndex() 方法重建集合的索引。reIndex() 方法首先删除所有索引,然后重建所有索引。

语法

db.Collection_Name.reIndex()

示例

db.Demo.reIndex()

输出

{  
    "nIndexesWas": 3,  
    "nIndexes": 3,  
    "indexes": [{  
        "key": {  
            "_id": 1  
        },  
        "name": "_id_",  
        "ns": "Temp.Demo"  
    }, {  
        "key": {  
            "Name": 1  
        },  
        "name": "Name_1",  
        "ns": "Temp.Demo",  
        "expireAfterSeconds": 12  
    }, {  
        "key": {  
            "Id": 1  
        },  
        "name": "Id_1",  
        "ns": "Temp.Demo"  
    }],  
    "ok": 1  
}  

Indexes.find() 方法 index.find()

方法返回数据库所有集合的所有索引的列表。

语法

db.system.indexes.find()

示例

db.system.indexes.find()

输出

{  
    "v": 1,  
    "key": {  
        "_id": 1  
    },  
    "name": "_id_",  
    "ns": "Temp.Employee_Deatils"  
} {  
    "v": 1,  
    "key": {  
        "_id": 1  
    },  
    "name": "_id_",  
    "ns": "Temp.Employee_Details"  
} {  
    "v": 1,  
    "key": {  
        "_id": 1  
    },  
    "name": "_id_",  
    "ns": "Temp.pan"  
} {  
    "v": 1,  
    "key": {  
        "_id": 1  
    },  
    "name": "_id_",  
    "ns": "Temp.post"  
} {  
    "v": 1,  
    "key": {  
        "_id": 1  
    },  
    "name": "_id_",  
    "ns": "Temp.ram"  
} {  
    "v": 1,  
    "key": {  
        "_id": 1  
    },  
    "name": "_id_",  
    "ns": "Temp.Test"  
} {  
    "v": 1,  
    "key": {  
        "_id": 1  
    },  
    "name": "_id_",  
    "ns": "Temp.City_Info"  
} {  
    "v": 1,  
    "key": {  
        "_id": 1  
    },  
    "name": "_id_",  
    "ns": "Temp.Post"  
} {  
    "v": 1,  
    "key": {  
        "_id": 1  
    },  
    "name": "_id_",  
    "ns": "Temp.Employee"  
} {  
    "v": 1,  
    "key": {  
        "Name": 1  
    },  
    "name": "Name_1",  
    "ns": "Temp.Employee"  
} {  
    "v": 1,  
    "key": {  
        "Likes": 1  
    },  
    "name": "Likes_1",  
    "ns": "Temp.post"  
} {  
    "v": 1,  
    "key": {  
        "Likedfs": 1  
    },  
    "name": "Likedfs_1",  
    "ns": "Temp.post"  
} {  
    "v": 1,  
    "key": {  
        "Likedfgdfs": 1  
    },  
    "name": "Likedfgdfs_1",  
    "ns": "Temp.post"  
} {  
    "v": 1,  
    "key": {  
        "Comment.CommentBy": 1  
    },  
    "name": "Comment.CommentBy_1",  
    "ns": "Temp.po  
st"  
}  

今天我们学习了索引,它们的类型和索引的一些基本方法。在下一篇文章中,我们将学习聚合。

感谢您阅读这篇文章!

下一篇 >> MongoDB 聚合(第 14 天)


慕源网 » MongoDB 索引(第 13 天)

常见问题FAQ

程序仅供学习研究,请勿用于非法用途,不得违反国家法律,否则后果自负,一切法律责任与本站无关。
请仔细阅读以上条款再购买,拍下即代表同意条款并遵守约定,谢谢大家支持理解!

发表评论

开通VIP 享更多特权,建议使用QQ登录