Administración de directivas de indexación en Azure Cosmos DB

SE APLICA A: NoSQL

En Azure Cosmos DB, para indexar los datos se usan las directivas de indexación que se definen para cada contenedor. La directiva de indexación predeterminada para los contenedores recién creados exige que se usen índices de intervalo para todas las cadenas o números. Puede invalidar esta directiva con su propia directiva de indexación personalizada.

Nota

El método de actualización de las directivas de indexación que se describe en este artículo solo se aplica a Azure Cosmos DB for NoSQL. Obtenga información sobre la indexación en Azure Cosmos DB for MongoDB e Indexación secundaria en Azure Cosmos DB for Apache Cassandra.

Ejemplos de directiva de indexación

Estos son algunos ejemplos de directivas de indexación que se muestran en formato JSON. Se exponen en Azure Portal en formato JSON. Los mismos parámetros se pueden establecer a través de la CLI de Azure o cualquier SDK.

Directiva de rechazo que excluye de forma selectiva algunas rutas de acceso de propiedades

{
    "indexingMode": "consistent",
    "includedPaths": [
        {
            "path": "/*"
        }
    ],
    "excludedPaths": [
        {
            "path": "/path/to/single/excluded/property/?"
        },
        {
            "path": "/path/to/root/of/multiple/excluded/properties/*"
        }
    ]
}

Directiva de participación que incluye de forma selectiva algunas rutas de acceso de propiedades

{
    "indexingMode": "consistent",
    "includedPaths": [
        {
            "path": "/path/to/included/property/?"
        },
        {
            "path": "/path/to/root/of/multiple/included/properties/*"
        }
    ],
    "excludedPaths": [
        {
            "path": "/*"
        }
    ]
}

Nota:

Por lo general, se recomienda usar una directiva de indexación de exclusión. Azure Cosmos DB indexa, de manera proactiva, todas las propiedades nuevas que se agregan a su modelo de datos.

Uso de un índice espacial en una ruta de acceso de una propiedad concreta solo

{
    "indexingMode": "consistent",
    "automatic": true,
    "includedPaths": [
        {
            "path": "/*"
        }
    ],
    "excludedPaths": [
        {
            "path": "/_etag/?"
        }
    ],
    "spatialIndexes": [
        {
            "path": "/path/to/geojson/property/?",
            "types": [
                "Point",
                "Polygon",
                "MultiPolygon",
                "LineString"
            ]
        }
    ]
}

Ejemplos de la directiva de índice compuesto

Además de incluir o excluir rutas de acceso para las propiedades individuales, también puede especificar un índice compuesto. Para realizar una consulta que tenga una cláusula ORDER BY para varias propiedades, se necesita un índice compuesto en esas propiedades. Si la consulta incluye filtros junto con la ordenación en varias propiedades, es posible que necesite más de un índice compuesto.

Los índices compuestos tienen también una ventaja de rendimiento para las consultas con varios filtros, o bien, con un filtro y una cláusula ORDER BY.

Nota:

Las rutas de acceso compuestas tienen un carácter /? implícito, ya que solo se indexa el valor escalar de esa ruta de acceso. El carácter comodín /* no se admite en las rutas de acceso compuestas. No debe especificar /? ni /* en las rutas de acceso compuestas. Las rutas de acceso compuestas también distinguen mayúsculas de minúsculas.

Índice compuesto definido para (name asc, age desc)

{  
    "automatic":true,
    "indexingMode":"Consistent",
    "includedPaths":[  
        {  
            "path":"/*"
        }
    ],
    "excludedPaths":[],
    "compositeIndexes":[  
        [  
            {  
                "path":"/name",
                "order":"ascending"
            },
            {  
                "path":"/age",
                "order":"descending"
            }
        ]
    ]
}

El índice compuesto en name y age es necesario para las siguientes consultas:

Consulta 1:

SELECT *
FROM c
ORDER BY c.name ASC, c.age DESC

Consulta 2:

SELECT *
FROM c
ORDER BY c.name DESC, c.age ASC

Este índice compuesto beneficia a las siguientes consultas y optimiza los filtros:

Consulta #3:

SELECT *
FROM c
WHERE c.name = "Tim"
ORDER BY c.name DESC, c.age ASC

Consulta #4:

SELECT *
FROM c
WHERE c.name = "Tim" AND c.age > 18

Índice compuesto definido para (name ASC, age ASC) y (name ASC, age DESC)

Puede definir varios índices compuestos dentro de la misma directiva de índice.

{  
    "automatic":true,
    "indexingMode":"Consistent",
    "includedPaths":[  
        {  
            "path":"/*"
        }
    ],
    "excludedPaths":[],
    "compositeIndexes":[  
        [  
            {  
                "path":"/name",
                "order":"ascending"
            },
            {  
                "path":"/age",
                "order":"ascending"
            }
        ],
        [  
            {  
                "path":"/name",
                "order":"ascending"
            },
            {  
                "path":"/age",
                "order":"descending"
            }
        ]
    ]
}

Índice compuesto definido para (name ASC, age ASC)

Si quiere, puede especificar el orden. Si no lo especifica, el orden es ascendente.

{  
    "automatic":true,
    "indexingMode":"Consistent",
    "includedPaths":[  
        {  
            "path":"/*"
        }
    ],
    "excludedPaths":[],
    "compositeIndexes":[  
        [  
            {  
               "path":"/name"
            },
            {  
               "path":"/age"
            }
        ]
    ]
}

Excluir las rutas de acceso de todas las propiedades, pero mantener la indexación activa

Puede usar esta directiva en las situaciones en que la característica Período de vida (TTL) esté activa, pero no se necesite ningún otro índice para usar Azure Cosmos DB como almacén de pares clave-valor puro.

{
    "indexingMode": "consistent",
    "includedPaths": [],
    "excludedPaths": [{
        "path": "/*"
    }]
}

Sin indexación

Esta directiva desactiva la indexación. Si indexingMode está establecido en none, no puede establecer un TTL en el contenedor.

{
    "indexingMode": "none"
}

Actualización de la directiva de indexación

En Azure Cosmos DB, la directiva de indexación se puede actualizar mediante cualquiera de los métodos siguientes:

  • Desde Azure Portal
  • Uso de la CLI de Azure
  • Usar PowerShell
  • Con uno de los SDK

Las actualizaciones de las directivas de indexación desencadenan transformaciones de índices. También se puede realizar un seguimiento del progreso de esta transformación desde los SDK.

Nota:

Al actualizar la directiva de indexación, las escrituras en Azure Cosmos DB no se interrumpen. Obtenga más información sobre las transformaciones de indexación.

Importante

La eliminación de un índice tiene efecto inmediatamente, mientras que agregar uno nuevo tarda algún tiempo, ya que requiere una transformación de indexación. Al reemplazar un índice por otro (por ejemplo, reemplazar un solo índice de propiedad por un índice compuesto), asegúrese de agregar primero el nuevo índice y, a continuación, esperar a que se complete la transformación del índice antes de quitar el índice anterior de la directiva de indexación. De lo contrario, esto afectará negativamente a la capacidad de consultar el índice anterior y podría interrumpir las cargas de trabajo activas que hagan referencia al índice anterior.

Uso de Azure Portal

Los contenedores de Azure Cosmos DB almacenan su directiva de indexación en forma de documento JSON que Azure Portal permite editar directamente.

  1. Inicie sesión en Azure Portal.

  2. Cree una nueva cuenta de Azure Cosmos DB o seleccione una existente.

  3. Abra el panel Data Explorer y seleccione el contenedor en el que quiere trabajar.

  4. Seleccione Escala y Configuración.

  5. Modifique el documento JSON de la directiva de indexación, como se muestra en estos ejemplos.

  6. Cuando haya terminado, haga clic en Guardar.

Manage Indexing using Azure portal

Uso de la CLI de Azure

Para crear un contenedor con una directiva de indexación personalizada, consulte Creación de un contenedor con una directiva de indexación personalizada mediante la CLI.

Uso de PowerShell

Para crear un contenedor con una directiva de indexación personalizada, consulte Creación de un contenedor con una directiva de indexación personalizada mediante PowerShell.

Uso del SDK de .NET

El objeto ContainerProperties del SDK de .NET v3 expone una propiedad IndexingPolicy que permite cambiar IndexingMode y agregar o quitar IncludedPaths y ExcludedPaths. Para más información, consulte Inicio rápido: Biblioteca cliente de Azure Cosmos DB for NoSQL para .NET.

// Retrieve the container's details
ContainerResponse containerResponse = await client.GetContainer("database", "container").ReadContainerAsync();
// Set the indexing mode to consistent
containerResponse.Resource.IndexingPolicy.IndexingMode = IndexingMode.Consistent;
// Add an included path
containerResponse.Resource.IndexingPolicy.IncludedPaths.Add(new IncludedPath { Path = "/*" });
// Add an excluded path
containerResponse.Resource.IndexingPolicy.ExcludedPaths.Add(new ExcludedPath { Path = "/name/*" });
// Add a spatial index
SpatialPath spatialPath = new SpatialPath
{
    Path = "/locations/*"
};
spatialPath.SpatialTypes.Add(SpatialType.Point);
containerResponse.Resource.IndexingPolicy.SpatialIndexes.Add(spatialPath);
// Add a composite index
containerResponse.Resource.IndexingPolicy.CompositeIndexes.Add(new Collection<CompositePath> { new CompositePath() { Path = "/name", Order = CompositePathSortOrder.Ascending }, new CompositePath() { Path = "/age", Order = CompositePathSortOrder.Descending } });
// Update container with changes
await client.GetContainer("database", "container").ReplaceContainerAsync(containerResponse.Resource);

Para realizar un seguimiento del progreso de transformación del índice, utilice un objeto RequestOptions que establezca la propiedad PopulateQuotaInfo en true. Recupere el valor del encabezado de respuesta x-ms-documentdb-collection-index-transformation-progress.

// retrieve the container's details
ContainerResponse containerResponse = await client.GetContainer("database", "container").ReadContainerAsync(new ContainerRequestOptions { PopulateQuotaInfo = true });
// retrieve the index transformation progress from the result
long indexTransformationProgress = long.Parse(containerResponse.Headers["x-ms-documentdb-collection-index-transformation-progress"]);

Al definir una directiva de indexación personalizada durante la creación de un nuevo contenedor, la API fluida del SDK v3 le permite escribir esta definición de una manera concisa y eficaz:

await client.GetDatabase("database").DefineContainer(name: "container", partitionKeyPath: "/myPartitionKey")
    .WithIndexingPolicy()
        .WithIncludedPaths()
            .Path("/*")
        .Attach()
        .WithExcludedPaths()
            .Path("/name/*")
        .Attach()
        .WithSpatialIndex()
            .Path("/locations/*", SpatialType.Point)
        .Attach()
        .WithCompositeIndex()
            .Path("/name", CompositePathSortOrder.Ascending)
            .Path("/age", CompositePathSortOrder.Descending)
        .Attach()
    .Attach()
    .CreateIfNotExistsAsync();

Uso del SDK de Java

El objeto DocumentCollection del SDK de Java expone los métodos getIndexingPolicy() y setIndexingPolicy(). El objeto IndexingPolicy que manipulan permite cambiar el modo de indexación y agregar o quitar las rutas de acceso incluidas y excluidas. Para más información, consulte Inicio rápido: Compilación de una aplicación Java para administrar los datos de Azure Cosmos DB for NoSQL.

// Retrieve the container's details
Observable<ResourceResponse<DocumentCollection>> containerResponse = client.readCollection(String.format("/dbs/%s/colls/%s", "database", "container"), null);
containerResponse.subscribe(result -> {
DocumentCollection container = result.getResource();
IndexingPolicy indexingPolicy = container.getIndexingPolicy();

// Set the indexing mode to consistent
indexingPolicy.setIndexingMode(IndexingMode.Consistent);

// Add an included path

Collection<IncludedPath> includedPaths = new ArrayList<>();
IncludedPath includedPath = new IncludedPath();
includedPath.setPath("/*");
includedPaths.add(includedPath);
indexingPolicy.setIncludedPaths(includedPaths);

// Add an excluded path

Collection<ExcludedPath> excludedPaths = new ArrayList<>();
ExcludedPath excludedPath = new ExcludedPath();
excludedPath.setPath("/name/*");
excludedPaths.add(excludedPath);
indexingPolicy.setExcludedPaths(excludedPaths);

// Add a spatial index

Collection<SpatialSpec> spatialIndexes = new ArrayList<SpatialSpec>();
Collection<SpatialType> collectionOfSpatialTypes = new ArrayList<SpatialType>();

SpatialSpec spec = new SpatialSpec();
spec.setPath("/locations/*");
collectionOfSpatialTypes.add(SpatialType.Point);
spec.setSpatialTypes(collectionOfSpatialTypes);
spatialIndexes.add(spec);

indexingPolicy.setSpatialIndexes(spatialIndexes);

// Add a composite index

Collection<ArrayList<CompositePath>> compositeIndexes = new ArrayList<>();
ArrayList<CompositePath> compositePaths = new ArrayList<>();

CompositePath nameCompositePath = new CompositePath();
nameCompositePath.setPath("/name");
nameCompositePath.setOrder(CompositePathSortOrder.Ascending);

CompositePath ageCompositePath = new CompositePath();
ageCompositePath.setPath("/age");
ageCompositePath.setOrder(CompositePathSortOrder.Descending);

compositePaths.add(ageCompositePath);
compositePaths.add(nameCompositePath);

compositeIndexes.add(compositePaths);
indexingPolicy.setCompositeIndexes(compositeIndexes);

// Update the container with changes

 client.replaceCollection(container, null);
});

Para realizar un seguimiento del progreso de transformación del índice en un contenedor, utilice un objeto RequestOptions que solicite la información de cuota que se debe rellenar. Recupere el valor del encabezado de respuesta x-ms-documentdb-collection-index-transformation-progress.

// set the RequestOptions object
RequestOptions requestOptions = new RequestOptions();
requestOptions.setPopulateQuotaInfo(true);
// retrieve the container's details
Observable<ResourceResponse<DocumentCollection>> containerResponse = client.readCollection(String.format("/dbs/%s/colls/%s", "database", "container"), requestOptions);
containerResponse.subscribe(result -> {
    // retrieve the index transformation progress from the response headers
    String indexTransformationProgress = result.getResponseHeaders().get("x-ms-documentdb-collection-index-transformation-progress");
});

Uso del SDK de Node.js

La interfaz ContainerDefinition del SDK de Node.js expone una propiedad indexingPolicy que le permite cambiar el indexingMode y agregar o quitar includedPaths y excludedPaths. Para más información, consulte Inicio rápido: Biblioteca cliente de Azure Cosmos DB for NoSQL para Node.js.

Recuperar los detalles del contenedor:

const containerResponse = await client.database('database').container('container').read();

Establecer el modo de indexación en coherente:

containerResponse.body.indexingPolicy.indexingMode = "consistent";

Agregar una ruta de acceso incluida con un índice espacial:

containerResponse.body.indexingPolicy.includedPaths.push({
    includedPaths: [
      {
        path: "/age/*",
        indexes: [
          {
            kind: cosmos.DocumentBase.IndexKind.Range,
            dataType: cosmos.DocumentBase.DataType.String
          },
          {
            kind: cosmos.DocumentBase.IndexKind.Range,
            dataType: cosmos.DocumentBase.DataType.Number
          }
        ]
      },
      {
        path: "/locations/*",
        indexes: [
          {
            kind: cosmos.DocumentBase.IndexKind.Spatial,
            dataType: cosmos.DocumentBase.DataType.Point
          }
        ]
      }
    ]
  });

Agregar una ruta de acceso excluida:

containerResponse.body.indexingPolicy.excludedPaths.push({ path: '/name/*' });

Actualizar el contenedor con cambios:

const replaceResponse = await client.database('database').container('container').replace(containerResponse.body);

Para realizar un seguimiento del progreso de transformación del índice en un contenedor, utilice un objeto RequestOptions que establezca la propiedad populateQuotaInfo en true. Recupere el valor del encabezado de respuesta x-ms-documentdb-collection-index-transformation-progress.

// retrieve the container's details
const containerResponse = await client.database('database').container('container').read({
    populateQuotaInfo: true
});
// retrieve the index transformation progress from the response headers
const indexTransformationProgress = replaceResponse.headers['x-ms-documentdb-collection-index-transformation-progress'];

Uso del SDK de Python

Cuando se usa el SDK de Python v3, la configuración del contenedor se administra como un diccionario. Desde este diccionario, puede acceder a la directiva de indexación y a todos sus atributos. Para más información, consulte Inicio rápido: Biblioteca cliente de Azure Cosmos DB for NoSQL para Python.

Recuperar los detalles del contenedor:

containerPath = 'dbs/database/colls/collection'
container = client.ReadContainer(containerPath)

Establecer el modo de indexación en coherente:

container['indexingPolicy']['indexingMode'] = 'consistent'

Definir una directiva de indexación con una ruta de acceso incluida y un índice espacial:

container["indexingPolicy"] = {

    "indexingMode":"consistent",
    "spatialIndexes":[
                {"path":"/location/*","types":["Point"]}
             ],
    "includedPaths":[{"path":"/age/*","indexes":[]}],
    "excludedPaths":[{"path":"/*"}]
}

Definir una directiva de indexación con una ruta de acceso excluida:

container["indexingPolicy"] = {
    "indexingMode":"consistent",
    "includedPaths":[{"path":"/*","indexes":[]}],
    "excludedPaths":[{"path":"/name/*"}]
}

Agregar un índice compuesto:

container['indexingPolicy']['compositeIndexes'] = [
                [
                    {
                        "path": "/name",
                        "order": "ascending"
                    },
                    {
                        "path": "/age",
                        "order": "descending"
                    }
                ]
                ]

Actualizar el contenedor con cambios:

response = client.ReplaceContainer(containerPath, container)

Pasos siguientes

Obtenga más información acerca de la indexación en los siguientes artículos: