DocumentDB - 索引记录
默认情况下,文档添加到数据库后,DocumentDB 会自动为文档中的每个属性建立索引。 但是,当存在不需要建立索引的特定文档和/或属性时,您可以控制并微调自己的索引策略,从而减少存储和处理开销。
告诉 DocumentDB 自动为每个属性建立索引的默认索引策略适用于许多常见场景。 但您也可以实施自定义策略,对哪些内容被索引、哪些内容不被索引以及与索引相关的其他功能进行精细控制。
DocumentDB 支持以下类型的索引 −
- 哈希
- 范围
哈希
哈希索引可以有效地查询相等性,即在搜索给定属性等于精确值的文档时,而不是匹配一系列值,例如小于、大于或之间。
您可以使用哈希索引执行范围查询,但 DocumentDB 将无法使用哈希索引来查找匹配文档,而是需要顺序扫描每个文档以确定是否应通过范围查询选择它。< /p>
您将无法在只有哈希索引的属性上使用 ORDER BY 子句对文档进行排序。
范围
为属性定义的范围索引,DocumentDB 允许根据一系列值有效地查询文档。 它还允许您使用 ORDER BY 对该属性的查询结果进行排序。
DocumentDB 允许您在任何或所有属性上定义哈希索引和范围索引,从而实现高效的相等和范围查询以及 ORDER BY。
索引政策
每个集合都有一个索引策略,规定每个文档的每个属性中的数字和字符串使用哪种类型的索引。
您还可以控制在将文档添加到集合中时是否自动为其建立索引。
默认情况下启用自动索引,但您可以在添加文档时覆盖该行为,告诉 DocumentDB 不要为该特定文档建立索引。
您可以禁用自动索引,以便默认情况下,文档在添加到集合中时不会被索引。 同样,您可以在文档级别覆盖它,并指示 DocumentDB 在将特定文档添加到集合时对其进行索引。 这称为手动索引。
包含/排除索引
索引策略还可以定义应在索引中包含或排除哪些路径。 如果您知道文档的某些部分您从不查询,而某些部分您查询过,那么这会非常有用。
在这些情况下,您可以通过告诉 DocumentDB 仅对添加到集合中的每个文档的特定部分建立索引来减少索引开销。
自动索引
让我们看一个自动索引的简单示例。
步骤 1 − 首先,我们创建一个名为自动索引的集合,并且在没有显式提供策略的情况下,该集合使用默认索引策略,这意味着在此集合上启用了自动索引。
这里我们对数据库自链接使用基于 ID 的路由,因此在创建集合之前我们不需要知道其资源 ID 或查询它。 我们可以只使用数据库 ID,即 mydb。
步骤 2 − 现在让我们创建两个文档,都使用 Upston 的姓氏。
private async static Task AutomaticIndexing(DocumentClient client) { Console.WriteLine(); Console.WriteLine("**** Override Automatic Indexing ****"); // 创建具有自动索引的集合 var collectionDefinition = new DocumentCollection { Id = "autoindexing" }; var collection = await client.CreateDocumentCollectionAsync("dbs/mydb", collectionDefinition); // Add a document (indexed) dynamic indexedDocumentDefinition = new { id = "MARK", firstName = "Mark", lastName = "Upston", addressLine = "123 Main Street", city = "Brooklyn", state = "New York", zip = "11229", }; Document indexedDocument = await client .CreateDocumentAsync("dbs/mydb/colls/autoindexing", indexedDocumentDefinition); // Add another document (request no indexing) dynamic unindexedDocumentDefinition = new { id = "JANE", firstName = "Jane", lastName = "Upston", addressLine = "123 Main Street", city = "Brooklyn", state = "New York", zip = "11229", }; Document unindexedDocument = await client .CreateDocumentAsync("dbs/mydb/colls/autoindexing", unindexedDocumentDefinition, new RequestOptions { IndexingDirective = IndexingDirective.Exclude }); //Unindexed document won't get returned when querying on non-ID (or selflink) property var doeDocs = client.CreateDocumentQuery("dbs/mydb/colls/autoindexing", "SELECT * FROM c WHERE c.lastName = 'Doe'").ToList(); Console.WriteLine("Documents WHERE lastName = 'Doe': {0}", doeDocs.Count); // Unindexed document will get returned when using no WHERE clause var allDocs = client.CreateDocumentQuery("dbs/mydb/colls/autoindexing", "SELECT * FROM c").ToList(); Console.WriteLine("All documents: {0}", allDocs.Count); // Unindexed document will get returned when querying by ID (or self-link) property Document janeDoc = client.CreateDocumentQuery("dbs/mydb/colls/autoindexing", "SELECT * FROM c WHERE c.id = 'JANE'").AsEnumerable().FirstOrDefault(); Console.WriteLine("Unindexed document self-link: {0}", janeDoc.SelfLink); // Delete the collection await client.DeleteDocumentCollectionAsync("dbs/mydb/colls/autoindexing"); }
Mark Upston 的第一个被添加到集合中,然后立即根据默认索引策略自动编入索引。
但是,当添加 Mark Upston 的第二个文档时,我们已使用 IndexingDirective.Exclude 传递了请求选项,这明确指示 DocumentDB 不要索引该文档,尽管集合的索引策略如此。
我们对最后的两个文档有不同类型的查询。
步骤 3 − 让我们从 CreateDocumentClient 调用 AutomaticIndexing 任务。
private static async Task CreateDocumentClient() { // Create a new instance of the DocumentClient using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) { await AutomaticIndexing(client); } }
编译并执行上述代码后,您将收到以下输出。
**** Override Automatic Indexing **** Documents WHERE lastName = 'Upston': 1 All documents: 2 Unindexed document self-link: dbs/kV5oAA==/colls/kV5oAOEkfQA=/docs/kV5oAOEkfQACA AAAAAAAAA==/
正如您所看到的,我们有两个这样的文档,但查询仅返回 Mark 的文档,因为 Mark 的文档未建立索引。 如果我们再次查询,没有 WHERE 子句来检索集合中的所有文档,那么我们会得到包含两个文档的结果集,这是因为没有 WHERE 子句的查询总是返回未索引的文档。
我们还可以通过 ID 或自链接检索未索引的文档。 因此,当我们通过 Mark 的 ID MARK 查询其文档时,我们会看到 DocumentDB 会返回该文档,即使该文档未在集合中建立索引。
手动索引
让我们看一个通过覆盖自动索引进行手动索引的简单示例。
步骤 1 − 首先,我们将创建一个名为"manualindexing"的集合,并通过显式禁用自动索引来覆盖默认策略。 这意味着,除非我们另有要求,否则添加到此集合的新文档将不会被索引。
private async static Task ManualIndexing(DocumentClient client) { Console.WriteLine(); Console.WriteLine("**** Manual Indexing ****"); // Create collection with manual indexing var collectionDefinition = new DocumentCollection { Id = "manualindexing", IndexingPolicy = new IndexingPolicy { Automatic = false, }, }; var collection = await client.CreateDocumentCollectionAsync("dbs/mydb", collectionDefinition); // Add a document (unindexed) dynamic unindexedDocumentDefinition = new { id = "MARK", firstName = "Mark", lastName = "Doe", addressLine = "123 Main Street", city = "Brooklyn", state = "New York", zip = "11229", }; Document unindexedDocument = await client .CreateDocumentAsync("dbs/mydb/colls/manualindexing", unindexedDocumentDefinition); // Add another document (request indexing) dynamic indexedDocumentDefinition = new { id = "JANE", firstName = "Jane", lastName = "Doe", addressLine = "123 Main Street", city = "Brooklyn", state = "New York", zip = "11229", }; Document indexedDocument = await client.CreateDocumentAsync ("dbs/mydb/colls/manualindexing", indexedDocumentDefinition, new RequestOptions { IndexingDirective = IndexingDirective.Include }); //Unindexed document won't get returned when querying on non-ID (or selflink) property var doeDocs = client.CreateDocumentQuery("dbs/mydb/colls/manualindexing", "SELECT * FROM c WHERE c.lastName = 'Doe'").ToList(); Console.WriteLine("Documents WHERE lastName = 'Doe': {0}", doeDocs.Count); // Unindexed document will get returned when using no WHERE clause var allDocs = client.CreateDocumentQuery("dbs/mydb/colls/manualindexing", "SELECT * FROM c").ToList(); Console.WriteLine("All documents: {0}", allDocs.Count); // Unindexed document will get returned when querying by ID (or self-link) property Document markDoc = client .CreateDocumentQuery("dbs/mydb/colls/manualindexing", "SELECT * FROM c WHERE c.id = 'MARK'") .AsEnumerable().FirstOrDefault(); Console.WriteLine("Unindexed document self-link: {0}", markDoc.SelfLink); await client.DeleteDocumentCollectionAsync("dbs/mydb/colls/manualindexing"); }
步骤 2 − 现在我们将再次创建与之前相同的两个文档。 这次我们不会为 Mark 的文档提供任何特殊请求选项,因为馆藏的索引政策,该文档将不会被索引。
步骤 3 − 现在,当我们为 Mark 添加第二个文档时,我们使用 RequestOptions 和 IndexingDirective.Include 来告诉 DocumentDB 它应该对该文档建立索引,这会覆盖集合的索引策略,该策略表明它不应该索引。
我们对最后的两个文档有不同类型的查询。
步骤 4 − 让我们从 CreateDocumentClient 调用 ManualIndexing 任务。
private static async Task CreateDocumentClient() { // Create a new instance of the DocumentClient using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) { await ManualIndexing(client); } }
编译并执行上述代码后,您将收到以下输出。
**** Manual Indexing **** Documents WHERE lastName = 'Upston': 1 All documents: 2 Unindexed document self-link: dbs/kV5oAA==/colls/kV5oANHJPgE=/docs/kV5oANHJPgEBA AAAAAAAAA==/
同样,查询仅返回两个文档之一,但这一次,它返回我们明确要求为其建立索引的 Jane Doe。 但还是和以前一样,不使用 WHERE 子句的查询将检索集合中的所有文档,包括 Mark 的未索引文档。 我们还可以通过 ID 查询未索引的文档,即使未索引,DocumentDB 也会返回该 ID。