Sync DocumentDB to Azure Search

Sincronización de DocumentDB a Azure Search usando indexadores

Introducción

Si usamos DocumentDB para almacenar los datos de nuestra aplicación, y queremos habilitar la búsqueda de texto completo, mediante un servicio de Azure Search, la mejor opción es utilizar indexadores, que hagan el trabajo de sincronización de nuestros datos hacia el servicio de búsqueda. Actualmente esta funcionalidad no está disponible en el SDK de Azure Search, así que deberemos usar la API.

Conceptos

Azure Search soporta la creación y administración de orígenes de datos (data sources) (incluyendo DocumentDB) e indexadores (indexers) que operan contra estos orígenes de datos.

Un origen de datos especifica qué datos deben ser indexados, las credenciales para acceder a estos datos, y ls políticas para que Azure Search identifique eficientemente los cambios en los datos. Un origen de datos se define de forma independiente para poder ser usado con más de un indexador.

Un idexador describe como fluyen los datos desde un origen de datos hacia el índice de búsqueda. Debería considerarse la creación de un idexador por cada combinación de índice destino y origen de datos. Se pueden tener múltiples indexadores escribiendo en un mismo índice, pero un indexador puede escribir solamente en un índice. Un indexador se usa para:

  • Ejecutar una copia de única vez para poblar el índice.
  • Sincronizar un índice con los cambios en el origen de datos en un horario programado. Este horario es parte de la definición del indexador.
  • Invocar actualizaciones del índice bajo demanda cuando sea necesario.

Paso 1: Crear el origen de datos

Para crear el origen de datos, tenemos que hacer un HTTP POST con los siguientes headers:


POST https://%5BNombre del servicio de Search].search.windows.net/datasources?api-version=[api-version]
Content-Type: application/json
api-key: [Key de administrador del servicio de Search]

El valor de api-version es obligatorio, y debe ser versión 2015-02-28 o superior.

El body del request contiene la definición del origen de datos, que debe incluir los siguientes campos:

  • name: el nombre del origen de datos (debe ser en minúsculas).
  • type: usar documentdb.
  • credentials:
    • connectionString: Requerido. Especificar la información de conexión a la base de datos de Azure DocumentDB con el siguiente formato: AccountEndpoint=<url del endpoint de DocumentDB>;AccountKey=<key de autorización de DocumentDB>;Database=<id de la base de datos de DocumentDB>
  • container:
    • name: Requerido. Especificar la collection de DocumentDB a indexar.
    • query: Opcional. Se puede especificar una query para aplanar un JSON arbitrario a un esquema plano que Azure Search pueda indexar.
  • dataChangeDetectionPolicy: Opcional. Explicación a continuación.
  • dataDeletionDetectionPolicy: Opcional. Explicación a continuación.

Capturando los documentos modificados

El propósito de la política de detección de cambios es el de identificar eficientemente los items cambiados. Actualmente la única política soportada es la política High Water Mark usando la propiedad _ts de timestamp de última modificación provista por DocumentDB, y se especifica de la siguiente manera:


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

view raw

_tsSpec.json

hosted with ❤ by GitHub

También deberemos agregar el campo _ts en nuestra proyección y en el WHERE de nuestra consulta. Por ejemplo:


SELECT p.id, p.Titulo, p.Director, p.Genero, p._ts FROM Peliculas p WHERE p._ts > @HighWaterMark

Capturando los documentos eliminados

Cuando se borran elementos de nuestra base de datos, debemos eliminarlo también de nuestro índice. El propósito de la política de detección de eliminaciones es el de identificar eficientemente los documentos eliminados. Actualmente, la única política soportada es la de Soft Delete (el borrado lógico marcado de alguna manera), que se especifica como:


{
"@odata.type" : "#Microsoft.Azure.Search.SoftDeleteColumnDeletionDetectionPolicy",
"softDeleteColumnName" : "la propiedad que especifica si un documento fue eliminado",
"softDeleteMarkerValue" : "el valor que identifica a un documento como borrado"
}

view raw

softDelete.json

hosted with ❤ by GitHub

Deberemos incluir esta propiedad en la cláusula SELECT si estamos haciendo una proyección custom.

Ejemplo del body completo del Request


{
"name": "miorigendedatosdocumentdb",
"type": "documentdb",
"credentials": {
"connectionString": "AccountEndpoint=https://miServicioDocumentDb.documents.azure.com;AccountKey=miKeyDeAutorizacionDocDb;Database=idDeMiBaseDeDatosDocDb"
},
"container": {
"name": "idDeLaColeccionDocDb",
"query": "SELECT p.id, p.Titulo, p.Director, p.Genero, p._ts FROM Peliculas p WHERE p._ts > @HighWaterMark"
},
"dataChangeDetectionPolicy": {
"@odata.type": "#Microsoft.Azure.Search.HighWaterMarkChangeDetectionPolicy",
"highWaterMarkColumnName": "_ts"
},
"dataDeletionDetectionPolicy": {
"@odata.type": "#Microsoft.Azure.Search.SoftDeleteColumnDeletionDetectionPolicy",
"softDeleteColumnName": "borrado",
"softDeleteMarkerValue": "true"
}
}

Response

Si el origen de datos se creó correctamente, se recibirá un response HTTP 201 Created.

Paso 2: Crear un índice

Si todavía no tenemos un índice en nuestro servicio de Azure Search, deberemos crear uno. Podemos crearlo desde el nuevo portal de Azure, o vía API, con un POST HTTP:


POST https://%5BNombre del servicio de Search].search.windows.net/indexes?api-version=[api-version]
Content-Type: application/json
api-key: [Key de administrador del servicio de Search]

view raw

Create index

hosted with ❤ by GitHub

Deberemos asegurarnos que el schema de nuestro índice sea compatible con el schema de los documentos JSON de nuestra consulta:

 Tipo de dato JSON  Tipo de campo compatible en el índice destino
 Bool  Edm.Boolean, Edm.String
 Números que se ven como enteros  Edm.Int32, Edm.Int64, Edm.String
 Números que se ven como de punto flotante  Edm.Double, Edm.String
 Cadenas de texto  Edm.String
 Vectores de datos primitivos (EJ.: [«a», «b», «c»])  Collection(Edm.String)
 Cadenas de texto que se vean como fechas  Edm.DateTimeOffset, Edm.String
 Objetos JSON  No disponible

Ejemplo del body del Request


{
"name": "miindicedesearch",
"fields": [{
"name": "id",
"type": "Edm.String",
"key": true,
"searchable": false
}, {
"name": "descripcion",
"type": "Edm.String",
"filterable": false,
"sortable": false,
"facetable": false,
"suggestions": true
}]
}

Response

Si el índice se creó correctamente, recibiremos un response HTTP 201 Created.

Paso 3: Crear el indexador

Podemos crear un nuevo indexador haciendo un POST HTTP con los siguientes headers:


POST https://%5BNombre del servicio de Search].search.windows.net/indexers?api-version=[api-version]
Content-Type: application/json
api-key: [Key de administrador del servicio de Search]

view raw

Create indexer

hosted with ❤ by GitHub

En el body del request deberemos incluir la definición del indexador, que deberá incluir:

  • name: Requerido. El nombre del indexador.
  • dataSourceName: Requerido. El nombre del origen de datos.
  • targetIndexName: Requerido. El nombre del índice destino.
  • schedule: Opcional. Veremos esto a continuación.

Correr un indexador en forma recurrente

Si lo deseamos, podemos hacer que nuestro indexador se ejecute recurrentemente cada cierto tiempo, usando el campo schedule, junto con los siguientes datos:

  • interval: Requerido. Un valor de tiempo que indica cada cuando correrá el indexador. El menor intervalo permitido es de 5 minutos, y el más largo de 1 día. Debe estar formateado como un valor XSD «dayTimeDuration» (un subconjunto restringido del valor de duración ISO 8601). El patrón para esto es: P[nD][T[nH][nM]]. Por ejemplo: PT15M para ejecutar cada 15 minutos, PT2H para ejecutar cada 2 horas.
  • startTime: Requerido. Una especificación de fecha y hora UTC que especifica cuándo debería comenzar a ejecutarse el indexador.

Ejemplo del body del Request

El ejemplo crea un indexador que copia los datos del origen de datos creado en el Paso 1, al índice creado en el Paso 2, comenzando el 1 de abril de 2015, y corriendo una vez por hora.


{
"name" : "miindexadordesearch",
"dataSourceName" : "miorigendedatosdocumentdb",
"targetIndexName" : "miindicedesearch",
"schedule" : { "interval" : "PT1H", "startTime" : "2015-04-01T00:00:00Z" }
}

Response

Si el indexador fue creado correctamente recibiremos un response HTTP 201 Created.

Paso 4: Correr el indexador

Aparte de poder correr periódicamente, a horarios programados, un indexador puede ser invocado bajo demanda a través de un POST HTTP:


POST https://%5BNombre del servicio de Search].search.windows.net/indexers/[nombre del indexador]/run?api-version=[api-version]
api-key: [Key de administrador del servicio de Search]

view raw

Run indexer

hosted with ❤ by GitHub

Response

Si se invocó exitosamente el indexador, recibiremos un response HTTP 202 Accepted.

Paso 5: Obtener el estado del indexador

Con un GET HTTP podemos conocer el estado actual y el hostorial de ejecución de un indexador:


GET https://%5BNombre del servicio de Search].search.windows.net/indexers/[nombre del indexador]/status?api-version=[api-version]
api-key: [Key de administrador del servicio de Search]

view raw

Get status

hosted with ❤ by GitHub

Response

Recibiremos un response HTTP 200 OK, que en el body contiene el dato del estado del indexador, el resultado de la última corrida, y el historial de las invocaciones recientes (si existieran).

El response debería verse similar a lo siguiente:


{
"status":"running",
"lastResult": {
"status":"success",
"errorMessage":null,
"startTime":"2015-04-01T02:37:18.853Z",
"endTime":"2015-04-01T02:37:19.012Z",
"errors":[],
"itemsProcessed":2501,
"itemsFailed":0,
"initialTrackingState":null,
"finalTrackingState":null
},
"executionHistory":[ {
"status":"success",
"errorMessage":null,
"startTime":"2015-04-01T02:37:18.853Z",
"endTime":"2015-04-01T02:37:19.012Z",
"errors":[],
"itemsProcessed":2501,
"itemsFailed":0,
"initialTrackingState":null,
"finalTrackingState":null
}]
}

El historial de ejecución contiene las 50 ejecuciones completadas más recientes, en orden cronológico inverso.

Espero que les haya sido útil.

@gjbellmann

Más información

Si quieren aprender más sobre Azure Search, pueden ver una Introducción a Azure Search y Usando Azure Search desde .NET.

Si quieren aprender más sobre DocumentDB, pueden ver una Introducción a DocumentDB.

Anuncio publicitario

1 comentario en “Sincronización de DocumentDB a Azure Search usando indexadores

  1. Pingback: Sincronización de Azure SQL Database a Azure Search usando indexadores | Guillermo Bellmann

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.