默认情况下,只要将文档添加到数据库,DocumentDB就会自动为文档中的每个属性编制索引.但是,当存在永远不需要编制索引的特定文档和/或属性时,您可以控制并微调自己的索引策略,从而减少存储和处理开销.
默认索引策略告诉DocumentDB自动索引每个属性适用于许多常见场景.但是,您还可以实现一个自定义策略,该策略可以精确控制索引的内容以及索引的内容和其他功能.
DocumentDB支持以下类型的索引和减号;
哈希
范围
哈希索引可以有效地查询相等性,即在搜索给定属性等于精确值的文档时,而不是匹配一系列值,如less ./b>
您可以使用哈希索引执行范围查询,但DocumentDB将无法使用哈希索引查找匹配的文档,而是需要顺序扫描确定是否应该通过范围查询选择每个文档.
您将无法在仅具有哈希索引的属性上使用ORDER BY子句对文档进行排序.
为th定义的范围索引e属性,DocumentDB允许根据一系列值有效地查询文档.它还允许您使用ORDER BY对该属性的查询结果进行排序.
DocumentDB允许您在任何或所有属性上定义散列和范围索引,从而实现有效的平等和范围查询,以及ORDER BY.
每个集合都有一个索引策略,指示哪些类型的索引用于数字每个文档的每个属性中的字符串.
您还可以控制文档是否在添加时自动编入索引
默认情况下启用自动索引,但您可以在添加文档时覆盖该行为,告知DocumentDB不要索引该特定文档.
您可以禁用自动索引,以便默认情况下,文档在添加到集合时不会编入索引.同样,您可以在文档级别覆盖它,并指示DocumentDB在将特定文档添加到集合时对其进行索引.这称为手动索引.
索引策略也可以定义应在索引中包含或排除的路径.如果您知道文档的某些部分永远不会被查询以及您执行某些部分,那么这很有用.
在这些情况下,您可以通过告诉DocumentDB减少索引开销索引只是添加到集合中的每个文档的特定部分.
让我们看一个自动索引的简单示例./p>
第1步 : 首先,我们创建一个名为autoindexing的集合,并且没有显式提供策略,此集合使用默认的索引策略,这意味着在此集合上启用了自动索引.
这里我们使用ID-基于数据库自我链接的路由,因此在创建集合之前,我们不需要知道它的资源ID或查询.我们可以使用数据库ID,即mydb.
步骤2 : 现在让我们创建两个文件,两个文件都使用Upston的姓氏.
private async static Task AutomaticIndexing(DocumentClient client) { Console.WriteLine(); Console.WriteLine("**** Override Automatic Indexing ****"); // Create collection with 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,第一个被添加到集合中,然后立即根据默认的索引策略自动编入索引./p>
但是当添加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或自我链接检索未编制索引的文档.因此,当我们通过他的ID,MARK查询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查询未编制索引的文档,即使文档未编入索引,也会返回该文档.