NHibernate – Bulk Manipulation with SQL Native
Hace unos días atrás Fabio Maulo hice este anuncio (como siempre lo hace) en NHibernate-Hispano hablando sobre esta nueva característica disponible ya en el trunk de NHibernate: Bulk Manipulation.
Por ahora esta característica solamente funciona con SQL Nativo y aquí tenemos un ejemplo:
using (ISession s = sf.OpenSession()){ using(ITransaction tx = s.BeginTransaction()){ s.CreateSQLQuery("update Book set Price = Price*1.1") .ExecuteUpdate(); tx.Commit(); }
O así:
using (ISession s = sf.OpenSession()){ using(ITransaction tx = s.BeginTransaction()){ s.CreateSQLQuery("update Book set Price = Price*:increase") .SetDecimal("increase",1.1m) .ExecuteUpdate(); tx.Commit(); }
O de esta manera:
using (ISession s = sf.OpenSession()){ using(ITransaction tx = s.BeginTransaction()){ s.GetNamedQuery("change-book-price") .SetDecimal("value",1.1m) .ExecuteUpdate(); tx.Commit(); }
Y la named query para la última consulta es:
<sql-query name="change-book-price"> update Book set Price = Price*:value </sql-query>
Uno de los principales escenarios donde se presenta una desventaja de los ORM es que necesitan tener en memoria a todos los objetos que necesitan modificar, una modificación en masa. Ahora no es necesario hacer esto, se puede usar esta funcionalidad sin mayores complicaciones.
El ejemplo muestra a una simple entidad Book (libro) que además tiene una propiedad Price (precio). El update masivo muestra como actualizar la property Price de todas las entidades aumentando un 10 %.
Analyzers en Lucene.Net
En este post estábamos viendo la integración de Lucene.Net con NHibernate mediante NHibernate Search.
Lucene puede indexar texto desde muchas fuentes: PDF, HTML, Documentos de Word entre los más conocidos y esto es lo que hace a Lucene muy usado por muchas aplicaciones reales para solucionar problemas de búsqueda. Luego que Lucene parsea los documentos desde un medio rico, debe convertir este stream en un formato de tokens de texto plano para que los pueda digerir y así indexar el contenido. El paso previo a la indexación es el análisis, y para esto se utilizan Analyzers. Lucene provee algunas clases que se pueden utilizar por ejemplo: WhitespaceAnalyzer que se encarga de tokenizar el texto sin tener en cuenta los espacios en blanco; StopAnalyzer que elimina las StopWords en Inglés del texto para poder indexarlo, por ejemplo: the, an, a, that, this, entre otras.
Usando NHibernate Search, podemos realizar consultas contra los índices que mantiene Lucene, ya sea en Memoria o en el propio sistema de archivos. Este es un ejemplo de una consulta usando NHibernate Search:
QueryParser qp = new QueryParser("Summary", new StopAnalyzer()); IQuery NHQuery = s.CreateFullTextQuery(qp.Parse("series"), typeof(Book)); IList result = NHQuery.List();
QueryParser recibe como parámetro un Analyzer, en este caso StopAnalyzer. Utilizando este Analyzer, Lucene encuentra los términos de búsqueda dentro del texto de búsqueda. Esto no tiene nada que ver con el Analyzer que se configura Lucene al comienzo, que indica la manera en que se van a filtrar los tokens que van almacenarse al Index. Este analyzer realiza un filtro en el string de búsqueda para encontrar las keywords de referencia a buscar.
Para entender un poco más sobre los Analyzer, realicé esta aplicación de consola basado en los ejemplos en Java de Lucene In Action, bueno… en realidad solo fue una traducción de Java a C# de los ejemplos que había. La idea es probar que tokens de salida producen distintos Analyzers ante una entrada de texto:

En este ejemplo utilicé dos analyzer de Lucene y uno personalizado a unas cuantas Stop Words del Español: SpanishStopAnalyzer. El programa que utilicé para correr ejemplo pueden hacer un checkout de aquí.