Indexar dados do Azure Cosmos DB for NoSQL para consultas na Pesquisa de IA do Azure

Neste artigo, saiba como configurar um indexador que importa conteúdo do Azure Cosmos DB para NoSQL e o torna pesquisável no IA do Azure Search.

Este artigo complementa o artigo Criar um indexador com informações específicas do Cosmos DB. Ele usa as APIs REST para demonstrar um fluxo de trabalho de três partes comum a todos os indexadores: criar uma fonte de dados, criar um índice e criar um indexador. A extração de dados ocorre quando você envia a solicitação Criar Indexador.

Como a terminologia pode ser confusa, vale a pena observar que a indexação do Azure Cosmos DB e a indexação do Azure AI Search são operações diferentes. A indexação no Azure AI Search cria e carrega um índice de pesquisa em seu serviço de pesquisa.

Pré-requisitos

Definir a fonte de dados

A definição da fonte de dados especifica os dados a serem indexados, as credenciais e as políticas para identificar alterações nos dados. Uma fonte de dados é um recurso independente que pode ser usada por vários indexadores.

  1. Crie ou atualize uma fonte de dados para configurar sua definição:

    POST https://[service name].search.windows.net/datasources?api-version=2023-11-01
    Content-Type: application/json
    api-key: [Search service admin key]
    {
        "name": "[my-cosmosdb-ds]",
        "type": "cosmosdb",
        "credentials": {
          "connectionString": "AccountEndpoint=https://[cosmos-account-name].documents.azure.com;AccountKey=[cosmos-account-key];Database=[cosmos-database-name]"
        },
        "container": {
          "name": "[my-cosmos-db-collection]",
          "query": null
        },
        "dataChangeDetectionPolicy": {
          "@odata.type": "#Microsoft.Azure.Search.HighWaterMarkChangeDetectionPolicy",
        "  highWaterMarkColumnName": "_ts"
        },
        "dataDeletionDetectionPolicy": null,
        "encryptionKey": null,
        "identity": null
    }
    
  2. Defina "type" como "cosmosdb" (obrigatório). Se você estiver usando uma API de Pesquisa mais antiga versão 2017-11-11, a sintaxe para "type" será "documentdb". Caso contrário, para a 2019-05-06 e posterior, use "cosmosdb".

  3. Defina "credentials" como a cadeia de conexão. A próxima seção descreve os formatos compatíveis.

  4. Defina "container" como a coleção. A propriedade "name" é necessária e especifica a ID da coleção de banco de dados a ser indexada. A propriedade "query" é opcional. Use-o para mesclar um documento JSON arbitrário em um esquema simples que o IA do Azure Search pode indexar.

  5. Defina "dataChangeDetectionPolicy" se os dados forem voláteis e você quiser que o indexador selecione apenas os itens novos e atualizados nas execuções seguintes.

  6. Defina "dataDeletionDetectionPolicy" se desejar remover documentos de pesquisa de um índice de pesquisa quando o item de origem for excluído.

Credenciais e cadeias de conexão com suporte

Os indexadores podem se conectar a uma coleção usando as conexões a seguir.

Evite usar números de porta na URL do ponto de extremidade. Se você incluir o número da porta, a conexão falhará.

Cadeia de conexão de acesso completo
{ "connectionString" : "AccountEndpoint=https://<Cosmos DB account name>.documents.azure.com;AccountKey=<Cosmos DB auth key>;Database=<Cosmos DB database id>" }`
Obtenha a cadeia de conexão na página da conta do Azure Cosmos DB no portal do Azure selecionando Chaves no painel de navegação à esquerda. Você deve selecionar uma cadeia de conexão completa, não apenas uma chave.
Cadeia de conexão de identidade gerenciada
{ "connectionString" : "ResourceId=/subscriptions/<your subscription ID>/resourceGroups/<your resource group name>/providers/Microsoft.DocumentDB/databaseAccounts/<your cosmos db account name>/;(ApiKind=[api-kind];)/(IdentityAuthType=[identity-auth-type])" }
Essa cadeia de conexão não requer uma chave de conta, mas você deve ter um serviço de pesquisa que possa conectar-se usando uma identidade gerenciada. Para conexões direcionadas à SQL API, você pode omitir ApiKind da cadeia de conexão. Para obter mais informações sobre ApiKindcomo IdentityAuthTypeconfigurar uma conexão de indexador com um banco de dados do Azure Cosmos DB usando uma identidade gerenciada.

Usando consultas para formatar dados indexados

Na propriedade "query" em "container", é possível especificar uma consulta SQL para mesclar propriedades ou matrizes aninhadas, projetar propriedades JSON e filtrar os dados a serem indexados.

Documento de exemplo:

    {
        "userId": 10001,
        "contact": {
            "firstName": "andy",
            "lastName": "hoh"
        },
        "company": "microsoft",
        "tags": ["azure", "cosmosdb", "search"]
    }

Filtrar consulta:

SELECT * FROM c WHERE c.company = "microsoft" and c._ts >= @HighWaterMark ORDER BY c._ts

Consulta de mesclagem:

SELECT c.id, c.userId, c.contact.firstName, c.contact.lastName, c.company, c._ts FROM c WHERE c._ts >= @HighWaterMark ORDER BY c._ts

Consulta de projeção:

SELECT VALUE { "id":c.id, "Name":c.contact.firstName, "Company":c.company, "_ts":c._ts } FROM c WHERE c._ts >= @HighWaterMark ORDER BY c._ts

Consulta de mesclagem de matriz:

SELECT c.id, c.userId, tag, c._ts FROM c JOIN tag IN c.tags WHERE c._ts >= @HighWaterMark ORDER BY c._ts

Consultas sem suporte (DISTINCT e GROUP BY)

Não há suporte para consultas que usam a palavra-chave DISTINCT ou a cláusula GROUP BY. O IA do Azure Search depende paginação de consulta SQL para enumerar totalmente os resultados da consulta. A palavra-chave DISTINCT e as cláusulas GROUP BY não são compatíveis com os tokens de continuação usados para paginar os resultados.

Exemplos de consultas sem suporte:

SELECT DISTINCT c.id, c.userId, c._ts FROM c WHERE c._ts >= @HighWaterMark ORDER BY c._ts

SELECT DISTINCT VALUE c.name FROM c ORDER BY c.name

SELECT TOP 4 COUNT(1) AS foodGroupCount, f.foodGroup FROM Food f GROUP BY f.foodGroup

Embora o Azure Cosmos DB tenha uma solução alternativa para dar suporte paginação de consulta SQL com a palavra-chave DISTINCT usando a cláusula ORDER BY, ela não é compatível com o IA do Azure Search. A consulta retorna um único valor JSON, enquanto o IA do Azure Search espera um objeto JSON.

-- The following query returns a single JSON value and isn't supported by Azure AI Search
SELECT DISTINCT VALUE c.name FROM c ORDER BY c.name

Adicionar campos de pesquisa a um índice

Em um índice de pesquisa, adicione campos para aceitar os documentos JSON de origem ou a saída da projeção de consulta personalizada. Verifique se o esquema de índice de pesquisa é compatível com os dados de origem. Para o conteúdo no Azure Cosmos DB, o esquema de índice de pesquisa deve corresponder aos itens do Azure Cosmos DB na fonte de dados.

  1. Crie ou atualize um índice para definir campos de pesquisa que armazenam dados:

    POST https://[service name].search.windows.net/indexes?api-version=2023-11-01
    Content-Type: application/json
    api-key: [Search service admin key]
    {
        "name": "mysearchindex",
        "fields": [{
            "name": "rid",
            "type": "Edm.String",
            "key": true,
            "searchable": false
        }, 
        {
            "name": "description",
            "type": "Edm.String",
            "filterable": false,
            "searchable": true,
            "sortable": false,
            "facetable": false,
            "suggestions": true
        }
      ]
    }
    
  2. Crie um campo de chave do documento ("key": true). Para coleções particionadas, a chave de documento padrão é a propriedade _rid do Azure Cosmos DB, que o Azure AI Search renomeia automaticamente para rid porque os nomes de campo não podem começar com um caractere de sublinhado. Além disso, os valores _rid do Azure Cosmos DB contêm caracteres que são inválidos nos termos do Azure AI Search. Por esse motivo, os valores _rid são codificados em Base64.

  3. Crie mais campos para conteúdo mais pesquisável. Confira Criar um índice para obter detalhes.

Mapeamento de tipos de dados

Tipos de dados JSON Tipos de campo do IA do Azure Search
Bool Edm.Boolean, Edm.String
Números que se parecem com inteiros Edm.Int32, Edm.Int64, Edm.String
Números que se parecem com pontos flutuantes Edm.Double, Edm.String
String Edm.String
Matrizes de tipos primitivos, como ["a", "b" e "c"] Collection(Edm.String)
Cadeias de caracteres que se parecem com datas Edm.DateTimeOffset, Edm.String
Objetos GeoJSON, por exemplo, { "type": "Point", "coordinates": [long, lat] } Edm.GeographyPoint
Outros objetos JSON N/D

Configurar e executar o indexador do Azure Cosmos DB for NoSQL

Uma vez que o índice e a fonte de dados forem criados, será possível criar o indexador. A configuração do indexador especifica as entradas, os parâmetros e as propriedades que controlam os comportamentos de tempo de execução.

  1. Crie ou atualize um indexador dando um nome a ele e referenciando a fonte de dados e o índice de destino:

    POST https://[service name].search.windows.net/indexers?api-version=2023-11-01
    Content-Type: application/json
    api-key: [search service admin key]
    {
        "name" : "[my-cosmosdb-indexer]",
        "dataSourceName" : "[my-cosmosdb-ds]",
        "targetIndexName" : "[my-search-index]",
        "disabled": null,
        "schedule": null,
        "parameters": {
            "batchSize": null,
            "maxFailedItems": 0,
            "maxFailedItemsPerBatch": 0,
            "base64EncodeKeys": false,
            "configuration": {}
            },
        "fieldMappings": [],
        "encryptionKey": null
    }
    
  2. Especifique mapeamentos de campo se houver diferenças no nome ou tipo de campo, ou se você precisar de várias versões de um campo de origem no índice de pesquisa.

  3. Confira Criar um indexador para obter mais informações sobre outras propriedades.

Um indexador é executado automaticamente depois de criado. Você pode evitar isso definindo "desabilitado" como verdadeiro. Para controlar a execução do indexador, execute um indexador sob demanda ou coloque-o em um agendamento.

Checar o status do indexador

Para monitorar o histórico de execuções e o status do indexador, envie uma solicitação Obter Status do Indexador:

GET https://myservice.search.windows.net/indexers/myindexer/status?api-version=2023-11-01
  Content-Type: application/json  
  api-key: [admin key]

A resposta inclui o status e o número de itens processados. Ela deve ser parecida com o seguinte exemplo:

    {
        "status":"running",
        "lastResult": {
            "status":"success",
            "errorMessage":null,
            "startTime":"2022-02-21T00:23:24.957Z",
            "endTime":"2022-02-21T00:36:47.752Z",
            "errors":[],
            "itemsProcessed":1599501,
            "itemsFailed":0,
            "initialTrackingState":null,
            "finalTrackingState":null
        },
        "executionHistory":
        [
            {
                "status":"success",
                "errorMessage":null,
                "startTime":"2022-02-21T00:23:24.957Z",
                "endTime":"2022-02-21T00:36:47.752Z",
                "errors":[],
                "itemsProcessed":1599501,
                "itemsFailed":0,
                "initialTrackingState":null,
                "finalTrackingState":null
            },
            ... earlier history items
        ]
    }

O histórico de execuções contém até 50 execuções mais recentes, classificadas em ordem cronológica inversa, de modo que a execução mais recente apareça em primeiro lugar.

Como indexar documentos novos e alterados

Depois que um indexador preencher completamente um índice de pesquisa, o ideal será que o indexador seguinte seja executado para indexar de maneira incremental apenas os documentos novos e alterados no banco de dados.

Para habilitar a indexação incremental, defina a propriedade "dataChangeDetectionPolicy" na definição da fonte de dados. Essa propriedade informa o indexador de que o mecanismo de controle de alterações é usado nos dados.

Para indexadores do Azure Cosmos DB, a única política com suporte é a HighWaterMarkChangeDetectionPolicy que usa a propriedade _ts (carimbo de data/hora) fornecida pelo Azure Cosmos DB.

O seguinte exemplo mostra uma definição de fonte de dados com uma política de detecção de alteração:

"dataChangeDetectionPolicy": {
    "@odata.type": "#Microsoft.Azure.Search.HighWaterMarkChangeDetectionPolicy",
"  highWaterMarkColumnName": "_ts"
},

Indexação incremental e consultas personalizadas

Se estiver usando uma consulta personalizada para recuperar documentos, verifique se a consulta ordena os resultados pela coluna _ts. Isso permite a verificação periódica que o IA do Azure Search usa para fornecer progresso incremental na presença de falhas.

Em alguns casos, mesmo que a sua consulta contenha uma cláusula ORDER BY [collection alias]._ts, a IA do Azure Search poderá não inferir que a consulta é ordenada pelo_ts. Você pode informar ao IA do Azure Search que os resultados são ordenados definindo a propriedade de configuração assumeOrderByHighWaterMarkColumn.

Para especificar essa dica, crie ou atualize a definição do indexador da seguinte maneira:

{
    ... other indexer definition properties
    "parameters" : {
        "configuration" : { "assumeOrderByHighWaterMarkColumn" : true } }
} 

Indexando documentos excluídos

Quando as linhas são excluídas da coleção, normalmente, você também deseja excluí-las do índice de pesquisa. A finalidade de uma política de detecção de exclusão de dados é identificar de maneira eficaz dados excluídos. Atualmente, a única política com suporte é a política Soft Delete (a exclusão recebe algum tipo de marcador), que é especificada na definição de fonte de dados da seguinte forma:

"dataDeletionDetectionPolicy"": {
    "@odata.type" : "#Microsoft.Azure.Search.SoftDeleteColumnDeletionDetectionPolicy",
    "softDeleteColumnName" : "the property that specifies whether a document was deleted",
    "softDeleteMarkerValue" : "the value that identifies a document as deleted"
}

Se você estiver usando uma consulta personalizada, garanta que a propriedade referenciada por softDeleteColumnName seja projetada pela consulta.

O softDeleteColumnName precisa ser um campo de nível superior no índice. Não há suporte para o uso de campos aninhados em tipos de dados complexos como o softDeleteColumnName.

O seguinte exemplo cria uma fonte de dados com uma política de exclusão reversível:

POST https://[service name].search.windows.net/datasources?api-version=2023-11-01
Content-Type: application/json
api-key: [Search service admin key]

{
    "name": "[my-cosmosdb-ds]",
    "type": "cosmosdb",
    "credentials": {
        "connectionString": "AccountEndpoint=https://[cosmos-account-name].documents.azure.com;AccountKey=[cosmos-account-key];Database=[cosmos-database-name]"
    },
    "container": { "name": "[my-cosmos-collection]" },
    "dataChangeDetectionPolicy": {
        "@odata.type": "#Microsoft.Azure.Search.HighWaterMarkChangeDetectionPolicy",
        "highWaterMarkColumnName": "_ts"
    },
    "dataDeletionDetectionPolicy": {
        "@odata.type": "#Microsoft.Azure.Search.SoftDeleteColumnDeletionDetectionPolicy",
        "softDeleteColumnName": "isDeleted",
        "softDeleteMarkerValue": "true"
    }
}

Usar o .NET

Para os dados acessados por meio do protocolo da API do SQL, você pode usar o SDK do .NET para automatizá-los com indexadores. Recomendamos revisar a seção anterior da API REST para conhecer os conceitos, o fluxo de trabalho e os requisitos. Veja a seguinte documentação de referência da API do .NET para implementar um indexador JSON em um código gerenciado:

Próximas etapas

Você já pode controlar como executar o indexador, monitorar o status ou agendar a execução do indexador. Os seguintes artigos se aplicam aos indexadores que efetuam pull do conteúdo do Azure Cosmos DB: