Usando Azure Search desde .NET

En el post anterior vimos un poco de historia y cómo crear nuestro primer servicio, hoy vamos a ver cómo usar este servicio desde .NET.

Instalar el SDK oficial

Al momento de escribir este post, el SDK oficial se encuentra en la versión 0.9.7-preview, con lo cual soporta sólo una parte de la funcionalidad disponible en la API 2015-02-28, pero es suficiente para hacer las tareas más comunes. Está disponible en NuGet, bajo el nombre Microsoft.Azure.Search (no olvidarse de seleccionar «Include Prerelease» para que aparezca en el listado de búsqueda).

Escenarios

Los escenarios que vamos a estar viendo son:

  • Creación del índice.
  • Inserción de documentos en el índice.
  • Búsqueda de documentos usando la búsqueda de texto completo y los filtros.

Creación del índice

Lo primero que vamos a necesitar es crear nuestro SearchIndexClient:


public SearchServiceClient GetSearchServiceClient()
{
// El nombre del servicio es solamente la primera parte de la URL del servicio,
// ej.: https://miservicio.search.windows.net/
string searchServiceName = "miservicio";
string apiKey = "Aquí va una de las keys de administración."
SearchServiceClient serviceClient = new SearchServiceClient(searchServiceName, new SearchCredentials(apiKey));
return serviceClient;
}

Luego crearemos nuestro índice, como ejemplo, vamos a usar un índice muy simple de películas:


public void CreateIndex(SearchServiceClient searchServiceClient)
{
var index = new Index
{
Name = "peliculas",
Fields = new []
{
new Field("peliculaId", DataType.String) { IsKey = true },
new Field("titulo", DataType.String) { IsSearchable = true, IsFilterable = true },
new Field("director", DataType.String) { IsSearchable = true, IsFilterable = true, IsFacetable = true },
new Field("actores", DataType.Collection(DataType.String)) { IsSearchable = true, IsFilterable = true, IsFacetable = true },
new Field("genero", DataType.String) { IsFilterable = true, IsSortable = true, IsFacetable = true },
new Field("rating", DataType.Int32) { IsFilterable = true, IsSortable = true, IsFacetable = true },
new Field("fechaEstreno", DataType.DateTimeOffset) { IsFilterable = true, IsSortable = true, IsFacetable = true }
}
};
serviceClient.Indexes.Create(index);
}

view raw

CreateIndex.cs

hosted with ❤ by GitHub

Inserción de documentos en el índice

Para insertar documentos en el índice, primero vamos a ver cómo es el formato de esos documentos:


[SerializePropertyNamesAsCamelCase]
public class Pelicula
{
public string PeliculaId { get; set; }
public string Titulo { get; set; }
public string Director { get; set; }
public string[] Actores { get; set; }
public string Genero { get; set; }
public int? Rating { get; set; }
public DateTimeOffset? FechaEstreno { get; set; }
}

view raw

Pelicula.cs

hosted with ❤ by GitHub

El atributo SerializePropertyNamesAsCamelCase nos permite usar los nombres en Pascal case para nuestro código C#, y que sean convertidas a Camel case para ser serializados en JSON.

Debemos tener en cuenta que las propiedades Rating y FechaEstreno de nuestra clase son un int? y DateTimeOffset? respectivamente, esto es porque todos los campos primitivos de Azure Search son nullables.

Para poder insertar documentos en el índice, vamos a necesitar primero obtener un SearchIndexClient:


public SearchIndexClient GetIndexClientForPeliculas(SearchServiceClient serviceClient)
{
SearchIndexClient indexClient = serviceClient.Indexes.GetClient("peliculas");
return indexClient;
}

Y luego lo usamos para insertar documentos en el índice:


public void UploadDocuments(SearchIndexClient indexClient)
{
var documents = new Pelicula[]
{
new Pelicula
{
PeliculaId = "tt2084970",
Titulo = "El código enigma",
Director = "Morten Tyldum",
Actores = new [] { "Benedict Cumberbatch", "Keira Knightley", "Matthew Goode" },
Genero = "Drama",
Rating = 8,
FechaEstreno = new DateTimeOffset(2014, 12, 25, 0, 0, 0, TimeSpan.Zero),
},
new Pelicula
{
PeliculaId = "tt0816692",
Titulo = "Interestelar",
Director = "Christopher Nolan",
Actores = new [] { "Matthew McConaughey", "Anne Hathaway", "Jessica Chastain" },
Genero = "Ciencia Ficción",
Rating = 9,
FechaEstreno = new DateTimeOffset(2014, 11, 7, 0, 0, 0, TimeSpan.Zero),
},
new Pelicula
{
PeliculaId = "tt1809398",
Titulo = "Inquebrantable",
Director = "Angelina Jolie",
Actores = new [] { "Jack O'Connell", "Takamasa Ishihara", "Domhnall Gleeson" },
Genero = "Drama",
Rating = 7,
FechaEstreno = new DateTimeOffset(2014, 12, 25, 0, 0, 0, TimeSpan.Zero),
},
new Pelicula
{
PeliculaId = "tt2278388",
Titulo = "El gran hotel Budapest",
Director = "Wes Anderson",
Actores = new [] { "Ralph Fiennes", "F. Murray Abraham", "Mathieu Amalric" },
Genero = "Comedia",
Rating = 8,
FechaEstreno = new DateTimeOffset(2014, 3, 28, 0, 0, 0, TimeSpan.Zero),
},
new Pelicula
{
PeliculaId = "tt2562232",
Titulo = "Birdman o (La inesperada virtud de la ignorancia)",
Director = "Alejandro González Iñárritu",
Actores = new [] { "Michael Keaton", "Zach Galifianakis", "Edward Norton" },
Genero = "Drama",
Rating = 8,
FechaEstreno = new DateTimeOffset(2014, 11, 14, 0, 0, 0, TimeSpan.Zero),
},
};
try
{
indexClient.Documents.Index(IndexBatch.Create(documents.Select(doc => IndexAction.Create(doc))));
}
catch (IndexBatchException e)
{
// Si el servicio está bajo carga, el indexado puede fallar para alguno de los documentos en el lote.
// Dependiendo de nuestra aplicación, deberemos tomar medidas para compensar este problema, como
// esperar y reintentar, para el ejemplo, simplemente los mostramos en la consola.
Console.WriteLine(
"No se pudo indexar los siguientes documentos: {0}",
String.Join(", ", e.IndexResponse.Results.Where(r => !r.Succeeded).Select(r => r.Key)));
}
// Esperamos que se complete el indexado (ya que es asíncrono).
Thread.Sleep(2000);
}

Búsqueda de documentos

Finalmente, podremos buscar documentos en nuestro índice, usando la búsqueda de texto completo y algunos filtros (opcionales):


public IEnumerable<Pelicula> SearchDocuments(SearchIndexClient indexClient, string searchText, string filter = null)
{
// Ejecutamos la búsqueda basada en un texto de búsqueda y filtros opcionales
var sp = new SearchParameters();
if (!String.IsNullOrEmpty(filter))
{
sp.Filter = filter;
}
DocumentSearchResponse<Pelicula> response = indexClient.Documents.Search<Pelicula>(searchText, sp);
foreach (SearchResult<Pelicula> result in response)
{
yield return result.Document;
}
}

Espero que les sirva para poder empezar a incorporar búsqueda en sus aplicaciones y sitios web.

@gjbellmann

Anuncio publicitario

3 comentarios en “Usando Azure Search desde .NET

  1. Pingback: Introducción a Azure Search | Guillermo Bellmann

  2. Pingback: Sincronización de DocumentDB a Azure Search usando indexadores | Guillermo Bellmann

  3. 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.