Muy buenas a todos.
Hoy, quiero empezar a hablar sobre un servicio al que tenía muchas ganas de dedicarle un tiempo, el servicio Azure Search. A lo largo de los próximos días haremos un overview completo sobre este servicio y veremos cómo funciona y qué podemos hacer con él.
El servicio Azure Search permite añadir una robusta experiencia de búsqueda a nuestras aplicaciones usando una API REST o una SDK .NET sin gestionar la infraestructura de búsqueda o llegar a ser un experto en búsqueda.
En el siguiente enlace, podréis ver una descripción más profunda sobre este servicio:
https://azure.microsoft.com/en-us/documentation/articles/search-what-is-azure-search/
En el post de hoy, vamos a ver cómo configurar el servicio de búsqueda y el primer paso a la hora de poder comenzar a trabajar con el mismo, los índices.
Configurando el servicio de búsqueda en Azure
Lo primero que debemos hacer es aprovisionar el servicio de búsqueda. Para ello, en el nuevo portal de Azure, iremos a Nuevo->Datos y almacenamiento->Búsqueda de Azure, como se ve en la siguiente imagen.
A continuación, tenemos que indicar los datos básicos de configuración del servicio: el nombre del servicio, el grupo de recursos al que pertenece, la ubicación y el nivel de precios.
Para este servicio disponemos de dos niveles de precios, con diferentes características que harán que en función de la finalidad del uso del servicio, elijamos uno u otro.
Una vez configurados todos los parámetros, pulsamos sobre crear y el servicio se aprovisionará, con lo que ya lo tendremos listo para usar.
Los índices en Azure Search
Un índice es el medio principal para organizar y buscar documentos en el servicio de búsqueda de Azure, similar a cómo se organizan los registros en una tabla de una base de datos. Cada índice tiene una colección de documentos que cumplen el esquema de índice (nombres de campo, tipos de datos y propiedades), pero los índices también especifican construcciones adicionales (proveedores de sugerencias, perfiles de puntuación y configuración de CORS) que definen otros comportamientos de la búsqueda.
Por tanto es necesario, como paso previo a subir documentos al servicio de búsqueda, definir un índice y su estructura, que no es más que una estructura de tablas que acepta datos y consultas. Los índices en el servicio de búsqueda de Azure, se pueden crear de tres formas, o desde el propio portal de Azure o por medio de código usando una SDK de .NET o una API REST.
A continuación, vamos a ver como crear un índice por medio de la SDK y la API REST en un solución de consola de Visual Studio.
Creando índices en Azure Search
Para ello, vamos a crear una aplicación de consola en Visual Studio. Una vez creada, tenemos que añadir las referencias a la SDK de Azure Search. Esto lo conseguiremos ejecutando en la consola de Nuget el siguiente comando:
Install-Package Microsoft.Azure.Search -Pre
Nos instalará todas las referencias necesarias para poder trabajar con la SDK correspondientes. Además, para el resto del ejemplo necesitaremos añadir otras dos referencias:
System.Configuration (Con la que tendremos la posibilidad de hacer referencia al App.Config de nuestra aplicación)
System.Net (Necesaria para poder llamadas REST desde la aplicación de consola).
Una vez añadidas todas las referencias, podemos pasar a ver el código. Para la aplicación de consola hemos creado un sencillo menú que nos permite elegir entre las dos opciones que tiene nuestra aplicación, crear un índice usando la SDK, o crear un índice por medio de API REST. Este es el código que implementa el menú:
class Program
{
static void Main(string[] args)
{
int option;
do
{
option = menu();
switch (option)
{
case 1:
SearchServiceClient serviceClient = GetSearchServiceClient();
DeleteIndexIfExists(serviceClient,"files");
CreateIndexUsingNetSDK(serviceClient,"files");
Console.WriteLine("Index successfully created");
break;
case 2:
SearchServiceClient serviceClient2 = GetSearchServiceClient();
DeleteIndexIfExists(serviceClient2,"files");
CreateIndexUsingRESTAPI("files");
break;
default:
break;
}
}
while (option != 0);
}
private static int menu()
{
int value = 0;
Console.WriteLine("-----------------------------------");
Console.WriteLine("1.- Create an index using .NET SDK");
Console.WriteLine("2.- Create an index using REST API");
Console.WriteLine("0.- Exit");
Console.WriteLine("-----------------------------------");
do
{
Console.WriteLine("Enter an valid option: ");
value = Int16.Parse(Console.ReadLine());
}
while (value < 0 && value > 2);
return value;
}
}
Como veréis, este código hace referencia a cuatro funciones, que son la clave de este post y que son en las que nos vamos a centrar para describir a continuación.
GetSearchServiceClient: Esta función nos va a devolver un objeto de tipo SearchServiceClient que es el que nos permite interaccionar con el servicio de búsqueda.
private static SearchServiceClient GetSearchServiceClient()
{
string serviceName = ConfigurationManager.AppSettings["SearchServiceName"];
string apiKey = ConfigurationManager.AppSettings["ApiKey"];
SearchServiceClient serviceClient = new SearchServiceClient(serviceName, new SearchCredentials(apiKey));
return serviceClient;
}
Este método solo se encarga de crear un nuevo objeto de tipo SearchServiceClient. El constructor de esta clase, recibe dos parámetros: el nombre del servicio que podemos obtener de la URL del servicio (https://%5Bnombreservicio%5D.search.windows.net) y la api-key para la autenticación del servicio. Ambos parámetros, para el ejemplo, los he almacenado en el App.Config de la aplicación de consola.
DeleteIndexIfExists: Una buena práctica, es comprobar si el índice existe previamente antes de crearlo y si es así, eliminarlo. De esto se encarga la función que vamos a ver a continuación:
private static void DeleteIndexIfExists(SearchServiceClient serviceClient, string indexName)
{
if (serviceClient.Indexes.Exists(indexName))
serviceClient.Indexes.Delete(indexName);
}
CreateIndexUsingNetSDK: Este método, crea un índice usando la SDK .NET de Azure Search.
private static void CreateIndexUsingNetSDK(SearchServiceClient serviceClient, string indexName)
{
var index = new Index()
{
Name = indexName,
Fields = new[]{
new Field("DocumentId",DataType.String) { IsKey = true, IsRetrievable = true, IsFilterable = true},
new Field("Name", DataType.String) { IsRetrievable = true, IsSearchable = true, IsFilterable = true},
new Field("Url", DataType.String) { IsRetrievable = true, IsSearchable = true, IsFilterable = true},
new Field("CreatedDate", DataType.String) { IsRetrievable = true, IsSearchable = true, IsFilterable = true}
}
};
serviceClient.Indexes.Create(index);
}
El método recibe como parámetros el objeto que hace referencia al servicio de búsqueda y el nombre del índice que vamos a crear. A continuación crea un objeto de tipo Index y le indica el nombre y los campos que va a tener dicho índice.
Cada campo se crea por medio de un objeto de tipo Field. El constructor de dicho objeto tiene dos parámetros, el nombre del campo y el tipo del mismo. Luego, podremos indicar otras propiedades de cada campo, como se ve en el ejemplo.
Por último, se crea el índice propiamente dicho con la llamada serviceClient.Indexes.Create(index) que vemos al final de la función.
CreateIndexUsingRESTAPI: La última función, crea un índice por medio de una llamada API REST.:
private static void CreateIndexUsingRESTAPI(string indexName)
{
string serviceName = ConfigurationManager.AppSettings["SearchServiceName"];
string apiKey = ConfigurationManager.AppSettings["ApiKey"];
string body = @"{
'name': '" + indexName + @"',
'fields': [
{'name': 'DocumentId', 'type': 'Edm.String', 'key': true, 'searchable': true},
{'name': 'Name', 'type': 'Edm.String'},
{'name': 'Url', 'type': 'Edm.String'},
{'name': 'CreatedDate', 'type': 'Edm.String'}
]
}";
using(var client = new HttpClient())
{
client.BaseAddress = new Uri("https://" + serviceName + ".search.windows.net");
client.DefaultRequestHeaders.Add("api-key", apiKey);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = client.PostAsync("/indexes?api-version=2015-02-28", new StringContent(body,Encoding.UTF8, "application/json")).Result;
if(response.IsSuccessStatusCode)
{
Console.WriteLine("Index successfully created");
}
else
{
Console.WriteLine("HTTP Status: " + response.StatusCode.ToString() + " - Reason: " + response.ReasonPhrase);
}
}
}
Esta función en primer lugar, crea una cadena de texto con la estructura JSON del índice, y la almacena en la variable body. A continuación, establece la URL base del servicio REST de Azure Search (https://%5Bnombreservicio%5D.search.windows.net).
Tras esto, hace la llamada haciendo uso de la clase HttpClient. A esta llamada, de tipo POST y con la URL (/indexes?api-version=2015-02-28), hay que añadirle en las cabeceras la api-key del servicio.
Una vez que se recibe la respuesta, podremos comprobar si hemos recibido un estado correcto, en cuyo caso el índice se habrá creado correctamente, o no.
Probando el ejemplo
Una vez terminado el código, si depuramos el ejemplo nos aparece una pantalla como la siguiente:
Pulsando sobre cualquier de las dos opciones, veremos que se ejecuta correctamente, y si accedemos posteriormente al portal de Azure, al servicio de búsqueda, veremos que el índice se ha creado.
Os voy a dejar algunos enlaces en los que me he basado y que os pueden resultar de interés.
https://azure.microsoft.com/en-us/services/search/
https://azure.microsoft.com/en-us/documentation/articles/search-get-started/
https://azure.microsoft.com/en-us/documentation/articles/search-howto-dotnet-sdk/
https://azure.microsoft.com/en-us/documentation/articles/search-create-service-portal/
Y esto es todo hasta aquí, en este post, hemos configurado y puesto en marcha el servicio de búsqueda creando los índices. En próximos posts, comenzaremos a indexar contenido y veremos cómo podemos hacerlo y consumiremos el servicio de búsqueda con todas las opciones de que disponemos para trabajar con el mismo.
Espero, como siempre, que os haya resultado interesante.
Hasta la próxima.