DocumentDB - Registros de indexación

De forma predeterminada, DocumentDB indexa automáticamente todas las propiedades de un documento tan pronto como el documento se agrega a la base de datos. Sin embargo, puede tomar el control y ajustar su propia política de indexación que reduce la sobrecarga de almacenamiento y procesamiento cuando hay documentos o propiedades específicos que nunca necesitan indexarse.

La política de indexación predeterminada que le dice a DocumentDB que indexe cada propiedad automáticamente es adecuada para muchos escenarios comunes. Pero también puede implementar una política personalizada que ejerza un control preciso sobre exactamente qué se indexa y qué no y otras funciones con respecto a la indexación.

DocumentDB admite los siguientes tipos de indexación:

  • Hash
  • Range

Picadillo

El índice hash permite una consulta eficiente para la igualdad, es decir, mientras se buscan documentos donde una propiedad dada es igual a un valor exacto, en lugar de coincidir en un rango de valores como menor que, mayor que o entre.

Puede realizar consultas de rango con un índice hash, pero DocumentDB no podrá usar el índice hash para encontrar documentos coincidentes y, en su lugar, deberá escanear secuencialmente cada documento para determinar si debe ser seleccionado por la consulta de rango.

No podrá ordenar sus documentos con una cláusula ORDER BY en una propiedad que solo tenga un índice hash.

Rango

Índice de rango definido para la propiedad, DocumentDB permite consultar de manera eficiente documentos contra un rango de valores. También le permite ordenar los resultados de la consulta en esa propiedad, usando ORDER BY.

DocumentDB le permite definir tanto un hash como un índice de rango en cualquiera o todas las propiedades, lo que permite consultas eficientes de igualdad y rango, así como ORDER BY.

Política de indexación

Cada colección tiene una política de indexación que dicta qué tipos de índices se utilizan para números y cadenas en cada propiedad de cada documento.

  • También puede controlar si los documentos se indexan automáticamente a medida que se agregan a la colección.

  • La indexación automática está habilitada de forma predeterminada, pero puede anular ese comportamiento al agregar un documento, indicando a DocumentDB que no indexe ese documento en particular.

  • Puede deshabilitar la indexación automática para que, de forma predeterminada, los documentos no se indexen cuando se agreguen a la colección. De manera similar, puede anular esto a nivel de documento e indicar a DocumentDB que indexe un documento en particular cuando lo agregue a la colección. Esto se conoce como indexación manual.

Incluir / excluir indexación

Una política de indexación también puede definir qué ruta o rutas deben incluirse o excluirse del índice. Esto es útil si sabe que hay ciertas partes de un documento que nunca consulta y ciertas partes que sí.

En estos casos, puede reducir la sobrecarga de indexación diciéndole a DocumentDB que indexe solo aquellas partes particulares de cada documento agregado a la colección.

Indexación automática

Echemos un vistazo a un ejemplo sencillo de indexación automática.

Step 1 - Primero creamos una colección llamada autoindexación y sin proporcionar explícitamente una política, esta colección usa la política de indexación predeterminada, lo que significa que la indexación automática está habilitada en esta colección.

Aquí estamos usando el enrutamiento basado en ID para el autoenlace de la base de datos, por lo que no necesitamos saber su ID de recurso o consultarlo antes de crear la colección. Podemos simplemente usar el ID de la base de datos, que es mydb.

Step 2 - Ahora creemos dos documentos, ambos con el apellido 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");
}

Este primero, para Mark Upston, se agrega a la colección y luego se indexa inmediatamente de forma automática según la política de indexación predeterminada.

Pero cuando se agrega el segundo documento para Mark Upston, pasamos las opciones de solicitud con IndexingDirective.Exclude, que indica explícitamente a DocumentDB que no indexe este documento, a pesar de la política de indexación de la colección.

Tenemos diferentes tipos de consultas tanto para los documentos al final.

Step 3 - Llamemos a la tarea AutomaticIndexing desde CreateDocumentClient.

private static async Task CreateDocumentClient() {
   // Create a new instance of the DocumentClient 
   using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) { 
      await AutomaticIndexing(client); 
   } 
}

Cuando se compile y ejecute el código anterior, recibirá el siguiente resultado.

**** Override Automatic Indexing **** 
Documents WHERE lastName = 'Upston': 1 
All documents: 2 
Unindexed document self-link: dbs/kV5oAA==/colls/kV5oAOEkfQA=/docs/kV5oAOEkfQACA 
AAAAAAAAA==/

Como puede ver, tenemos dos de esos documentos, pero la consulta solo devuelve el de Mark porque el de Mark no está indexado. Si consultamos nuevamente, sin una cláusula WHERE para recuperar todos los documentos de la colección, obtenemos un conjunto de resultados con ambos documentos y esto se debe a que los documentos no indexados siempre son devueltos por consultas que no tienen cláusula WHERE.

También podemos recuperar documentos no indexados por su ID o autoenlace. Entonces, cuando consultamos el documento de Mark por su ID, MARK, vemos que DocumentDB devuelve el documento aunque no esté indexado en la colección.

Indexación manual

Echemos un vistazo a un ejemplo simple de indexación manual anulando la indexación automática.

Step 1- Primero crearemos una colección llamada indexación manual y anularemos la política predeterminada desactivando explícitamente la indexación automática. Esto significa que, a menos que solicitemos lo contrario, los nuevos documentos agregados a esta colección no serán indexados.

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");
}

Step 2- Ahora crearemos nuevamente los mismos dos documentos que antes. No proporcionaremos ninguna opción de solicitud especial para el documento de Mark esta vez, debido a la política de indexación de la colección, este documento no se indexará.

Step 3 - Ahora, cuando agregamos el segundo documento para Mark, usamos RequestOptions con IndexingDirective.Include para decirle a DocumentDB que debe indexar este documento, lo que anula la política de indexación de la colección que dice que no debería.

Tenemos diferentes tipos de consultas tanto para los documentos al final.

Step 4 - Llamemos a la tarea ManualIndexing desde CreateDocumentClient.

private static async Task CreateDocumentClient() {
   // Create a new instance of the DocumentClient 
   using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
      await ManualIndexing(client); 
   } 
}

Cuando se compile y ejecute el código anterior, recibirá el siguiente resultado.

**** Manual Indexing **** 
Documents WHERE lastName = 'Upston': 1 
All documents: 2 
Unindexed document self-link: dbs/kV5oAA==/colls/kV5oANHJPgE=/docs/kV5oANHJPgEBA 
AAAAAAAAA==/

Nuevamente, la consulta devuelve solo uno de los dos documentos, pero esta vez, devuelve Jane Doe, que solicitamos explícitamente que se indexe. Pero nuevamente, como antes, al consultar sin una cláusula WHERE se recuperan todos los documentos de la colección, incluido el documento no indexado de Mark. También podemos consultar el documento no indexado por su ID, que DocumentDB devuelve aunque no esté indexado.