Chalalo Land

Tecnologías ASP.NET y un poco Más

Contacto


 Si quierer cooperar, yo feliz, muy agradecido :)

De donde me Visitan?

Locations of visitors to this page

Generic Content

Si te gustaron los articulos, y te animas te estaría muy agradecido!


Recent Posts

Tags

Community

Blogs de MVP

Amigos Geeks

Blogs Imperdibles

GODS

Archives

Email Notifications

Búsquedas de Texto con MongoDB y VB.NET ASP.NET Webform

image

Hola, si recueras mi post anterior sobre MongoDB y ASP.NET MVC, vimos como instalar mongoDB, instalar las librerías y utilizarlo junto a ASP.NET MVC. Esta vez veremos como utilizar ASP.NET Webforms con VB.NET junto a MongoDB para crear búsquedas de texto.

El problema

Tenemos aproximadamente 105.000 registros, que corresponden a un listado de diagnósticos posibles. Las búsquedas de texto siempre (o al menos la mayoría de las veces) son bastante costosas en términos de procesamiento, entonces para liberar la carga de nuestro ya exigido motor de BD, decidí utilizar mongoDB para estas búsquedas.

Los registros para la búsqueda tienen un código que se puede repetir y una descripción del diagnóstico, ej:

A244;Infeccion por Pseudomonas pseudomallei
A244;Melioidosis
A244;Neumoenteritis
A244;Neumonia debida a Pseudomonas pseudomallei
A250;Espirilosis
A250;Fiebre espirilar
A250;Fiebre mordedura debida Spirillum

No tengo idea que significan esos diagnósticos (y no me las doy de House MD). Entonces la idea e poder buscar por palabras, por ejemplo “mordedura” y “Spirillum” y obtener el o los registros concordante con los parámetros de búsqueda.

La Solución

Este post es parte de la solución, para eso armé un prototipo(que es el que ves en la siguiente imagen, un webform asp.net con vb.net)

La estructura, (si, Webform)

image

Diseño (si es que se puede llamar diseño)

image

Los botones AJ y KZ cargan los datos de lo archivos hacia mongoDB, y luego la búsqueda , consulta esos registros por las palabras ingresadas y lo muestra en el textarea.

Leyendo la documentación, revisé que se recomendaba crear un objeto con Keywords de búsqueda, es decir, las palabras relevantes, en mi caso todas las palabras que tengan más de 2 letras en la palabra. Veamos cual es la clase que utilizé: (Tapsa se llama el concepto de lista de diagnósticos)

    Class Tapsa

        <BsonId()> _

        Public Id As ObjectId

        Public codigo As String

        Public texto As String

        Public _keywords As List(Of String)

    End Class

Como ves, la _keywords es una lista de String, así que para cargar la lista de registros desde el archivo, voy a utilizar la siguiente función asociada a un botón(por el ejemplo), eliminando las palabras con menos de 3 letras.

 

Pero primero, la conexión a MongoDB


Private
Function DB() As MongoDatabase

        Dim server = MongoServer.Create("mongodb://localhost")

        Dim dbm As MongoDatabase = server.GetDatabase("sinetsur")

        Return dbm

End Function

 

Lueego el botón AJ, que hace lo mismo que el botón KZ, solo cambia el archivo:

 

Protected Sub Button1_Click(sender As Object, e As System.EventArgs) Handles Button1.Click

Dim sr As New StreamReader(Server.MapPath("ajC.csv"))

Dim linea As String = sr.ReadLine()

Dim tapsaas As MongoCollection(Of tapsa) = DB.GetCollection(Of tapsa)("tapsaas")

Do While linea <> Nothing

Dim tp As New Tapsa() With {.codigo = linea.Split(";")(0), .texto = 
  linea.Split(";")(1), ._keywords = divide(linea.Split(";")(1))}

  tapsaas.Insert(tp)

  linea = sr.ReadLine()
Loop

sr.Close()

End Sub

Y la función Divide, que devuelve un la lista  de String, ignorando las palabras “cortas”

Private Function divide(texto As String) As List(Of String)

  Dim lista As New List(Of String)

    For Each obj In texto.Split(" ").ToList

        If obj.Length > 2 Then

                lista.Add(obj.ToLower)

            End If

        Next

        Return lista

End Function

Con esto ya llené mi colección MongoDB, veamos como se visualiza la colección:

image

O si lo prefieres ver en formato JSON:

{
  "_id" : ObjectId("4edf74d4ac7d9820405ca343"),
  "codigo" : "A021",
  "texto" : "Septicemia debida a Salmonella cholerae-suis",
  "_keywords" : ["septicemia", "debida", "salmonella", "cholerae-suis"]
}

Puedes ver que existen 4 keywords y el texto era de 5 palabras, pero el “a” es totalmente ignorable.

Puedes probar en el Shell de MongoDB las búsquedas, por ejemplo escribimos lo siguiente en la consola:

db.tapsaas.find({"_keywords": { "$all": ["dolor","ojo"] }});

El resultado fue prácticamente inmediato, pero aún se puede ejecutar la consulta más rápido, esto es creando un índice por el campo keywords

db.tapsaas.ensureIndex({_keywords:1});

El proceso de creación del índice varia dependiendo de el campo al que se le aplica y a la cantidad de registros que ya existen en dicha colección. y bueno con esto creamos el índice, y ahora las búsquedas simplemente vuelan. (luego me referiré en detalle sobre el profiler de MongoDB, en otro post)

Ahora vamos revisar el código de  la búsqueda (botón Búsqueda).

Protected Sub Button2_Click(sender As Object, e As System.EventArgs) Handles Button2.Click

  tx_resultado.Text = ""

  Dim db__1 As MongoDatabase = DB()

  Dim ta As MongoCollection(Of Tapsa) = db__1.GetCollection(Of Tapsa)("tapsaas")

  Dim array As New List(Of String)

  array = divide(tx_texto.Text)

  Dim cont As Integer = 0

  Dim q = Query.All("_keywords", BsonArray.Create(array))

  For Each obj As Tapsa In ta.Find(q)

            tx_resultado.Text &= obj.codigo & " " & obj.texto & vbCrLf

            cont = cont + 1

  Next

  lb_cantidad.Text = cont

End Sub

 

Como puedes ver en el código, creamos la conexión a mongo, luego sobre el texto ingresado aplicamos la misma regla de eliminar las palabras “cortas” de menos de dos letras utilizando la misma función divide. Una vez que el array esta listo , creamos una query, buscando en el campo keywords y transformando a un BsonArray nuestra lista de string (array), luego hacemos un foreach sobre todas los registros resultantes de la búsqueda. Si hacemos un watch sobre la query vemos lo siguiente:

image

Lo que corresponde a la misma consulta que habíamos ejecutado en el Shell (texto resaltado en amarillo, a 20cm de acá, hacia arriba Lengua fuera)

Y luego mostramos los resultados en el tx_resultado (textarea), en el ejemplo siguiente busqué izquierdo:

image

La cantidad es 2.338 registros, es un tiempo muy reducido de tiempo, obviamente este sigue siendo un numero muy elevado de registros como para presentarlos al cliente, solo es para efectos de demostración, en producción la lógica es distinta, sin embargo, lo que quiero mostrar el la forma de buscar datos de texto dentro de una colección mongoDB.

Como siempre, te puedes bajar todo el código, incluyendo los registros para que pruebes:

image

Para la explicación de como instalar mongoDB en tu computador, revisa el Post Anterior

Saludos!
@chalalo

Posted: 7/12/2011 16:18 por Gonzalo Perez | con 2 comment(s) |
Archivado en: ,,
Comparte este post:

Comentarios

Kiquenet ha opinado:

Fantástico, gran post, para iniciados en este tema queda muy claro y le entran ganas de más !!! Saludos y gracias Chalalo.

# December 13, 2011 12:08 PM

MVP Factor ha opinado:

Lunes, 19 de diciembre Optimización de infrastructura SQL Server 1pm -6GMT Webcast

# December 19, 2011 7:37 PM