2010-02-19 9 views
62

Tengo asked a simlar question on Meta Stack Overflow, pero eso se refiere específicamente a si Lucene.NET se usa o no en Stack   Overflow.¿Cómo se usaría Lucene.NET para ayudar a implementar la búsqueda en un sitio como Stack Overflow?

El propósito de la pregunta aquí es más de un hipotética, en cuanto a lo que se acerca a uno haría que si fueran a utilizar Lucene.NET como base para la búsqueda en el sitio y otros factores en un sitio como Pila   Desbordamiento [SO].

De acuerdo con la entrada en el blog de desbordamiento de pila   titulado "SQL 2008 Full-Text Search Problems" hubo una fuerte indicación de que Lucene.NET estaba siendo considerado en algún momento, pero parece que definitivamente no es el caso, de acuerdo con el comentario por Geoff Dalgas el 19 de febrero de 2010:

Lucene.NET no está siendo utilizado para Stack Overflow - estamos utilizando SQL Server indexación de texto completo. La búsqueda es un área donde seguimos haciendo ajustes menores .

Así que mi pregunta es, ¿cómo se utilizan Lucene.NET en un sitio que tiene la misma semántica de Stack Overflow  ?

Aquí es un poco de antecedentes y lo que he hecho/pensamiento acerca de lo que va (sí, he estado poniendo en práctica la mayor parte de esto y de búsqueda es el último aspecto que tengo que completar):

Tecnologías:

Y por supuesto, la estrella del espectáculo, Lucene.NET.

La intención también es pasar a .NET/C# 4.0 lo antes posible. Si bien no creo que sea un cambio de juego, debe tenerse en cuenta.

Antes de entrar en aspectos de Lucene.NET, es importante señalar los aspectos de SQL Server 2008, así como los modelos involucrados.

Modelos

Este sistema tiene más de un tipo de modelo primario en comparación con Stack Overflow  . Algunos ejemplos de estos modelos son:

  • Preguntas: Estas son preguntas que las personas pueden formular. Las personas pueden responder preguntas, al igual que en Stack   Overflow.
  • Notas: Estas son proyecciones unidireccionales, por lo que a diferencia de una pregunta, usted está haciendo una declaración sobre el contenido. La gente no puede publicar respuestas a esto.
  • Eventos: se trata de datos sobre un evento en tiempo real. Tiene información de ubicación, información de fecha/hora.

Lo importante a tener en cuenta sobre estos modelos:

  • Todos ellos tienen un Nombre/Título (texto) propiedad y un cuerpo (HTML) propiedad (los formatos son irrelevantes, ya que el contenido será analizado apropiadamente para el análisis).
  • Cada instancia de un modelo tiene una URL única en el sitio

Luego están las cosas que se apilan   desbordamiento proporciona cuales la OMI, son decoradores a los modelos. Estos decoradores pueden tener diferentes cardinalidades, ya sea ser uno-a-uno o uno-a-muchos:

  • Votos: Afinado en el usuario
  • Respuestas: Opcional, como un ejemplo, véase el caso notas anteriores
  • Favorito: ¿El modelo aparece como favorito de un usuario?
  • Comentarios: (opcional)
  • Asociaciones de etiquetas: las etiquetas están en una tabla separada, para no duplicar la etiqueta de cada modelo. Hay un enlace entre el modelo y la tabla de asociaciones de etiquetas, y luego desde la tabla de asociaciones de etiquetas hasta la tabla de etiquetas.

Y hay recuentos de apoyo que en sí mismos son uno-a-uno decoradores a los modelos que tienen la forma adecuada para ellos de la misma manera (por lo general por un tipo de modelo de identificación y el modelo id):

  • Conteo de votos: total positivo, votos negativos, Wilson Score interval (esto es importante, determinará el nivel de confianza basado en los votos para una entrada, en su mayor parte, suponga el límite inferior del intervalo Wilson).

Las respuestas (respuestas) son modelos que tienen la mayoría de los decoradores que la mayoría de los modelos tienen, simplemente no tienen un título o una url, y si un modelo tiene una respuesta es opcional. Si se permiten respuestas, es por supuesto una relación de uno a muchos.

SQL Server 2008

Las tablas más o menos siguen el diseño de los modelos anteriores, con mesas separadas para los decoradores, así como algunas mesas de apoyo y vistas, procedimientos almacenados, etc.

Cabe señalar que la decisión de no utilizar la búsqueda de texto completo se basa principalmente en el hecho de que no normaliza puntajes como Lucene.NET. Estoy abierto a sugerencias sobre cómo utilizar la búsqueda basada en texto, pero tendré que realizar búsquedas en varios tipos de modelos, así que tenga en cuenta que voy a necesitar normalizar el puntaje de alguna manera.

Lucene.NET

Aquí es donde el gran signo de interrogación es. Aquí están mis pensamientos hasta ahora sobre Stack   Funcionalidad de desbordamiento, así como cómo y qué ya he hecho.

Indexación

Preguntas/Modelos

creo que cada modelo debe tener un índice de su propia que contiene un identificador único para buscar rápidamente hacia arriba sobre la base de una instancia plazo de ese id (indexados , no analizado).

En esta área, he considerado que Lucene.NET analice cada pregunta/modelo y cada respuesta individualmente. Entonces, si hubiera una pregunta y cinco respuestas, la pregunta y cada una de las respuestas se indexarían como una unidad por separado.

La idea aquí es que la puntuación de relevancia que devuelve Lucene.NET sería más fácil de comparar entre los modelos que se proyectan de diferentes maneras (por ejemplo, algo sin respuestas).

Como un ejemplo, una pregunta establece el tema, y ​​luego la respuesta profundiza sobre el tema.

Para una nota, que no tiene respuestas, maneja la cuestión de presentar el tema y luego elaborarlo.

Creo que esto ayudará a que los puntajes de relevancia sean más relevantes el uno para el otro.

Etiquetas

Al principio, pensé que éstos deben mantenerse en un índice separado con múltiples campos que tienen los identificadores a los documentos del índice modelo apropiado. O, si es demasiado grande, hay un índice con solo las etiquetas y otro índice que mantiene la relación entre el índice de etiquetas y las preguntas a las que se aplican. De esta manera, cuando se hace clic en una etiqueta (o utiliza la estructura de la URL), es fácil ver de una manera progresiva que es suficiente con "comprar en" si tiene éxito:

  • Si existe la etiqueta
  • que cuestiona las etiquetas están asociados con
  • las preguntas mismas

Sin embargo, en la práctica, haciendo una consulta de todos los elementos en función de las etiquetas (como hacer clic en una etiqueta en la pila   desbordamiento) es extremadamente fácil con SQL Server 2008. Basado en el modelo anterior, se requiere simplemente una consulta como:

select 
    m.Name, m.Body 
from 
    Models as m 
     left outer join TagAssociations as ta on 
      ta.ModelTypeId = <fixed model type id> and 
      ta.ModelId = m.Id 
     left outer join Tags as t on t.Id = ta.TagId 
where 
    t.Name = <tag> 

Y puesto que ciertas propiedades se comparten entre todos los modelos, es bastante fácil de hacer un UNION entre diferentes modelos Típicos/mesas y producir un conjunto coherente de resultados.

Esto sería análogo a un TermQuery en Lucene.NET (estoy haciendo referencia a la Java documentation ya que es integral, y Lucene.NET pretende ser una traducción línea por línea del Lucene, por lo que toda la documentación es el mismo).

El problema que surge con el uso de Lucene.NET aquí es el del orden de clasificación. El puntaje de relevancia para un TermQuery cuando se trata de etiquetas es irrelevante. Es 1 o 0 (lo tiene o no).

En este punto, el puntaje de confianza (intervalo de puntuación de Wilson) entra en juego para ordenar los resultados.

Este puntaje podría almacenarse en Lucene.NET, pero para ordenar los resultados en este campo, se basaría en los valores almacenados en la memoria caché de campo, que es algo que realmente quiero evitar. Para una gran cantidad de documentos, el caché de campo puede crecer mucho (el puntaje de Wilson es el doble, y necesitaría uno doble para cada documento, que puede ser un conjunto grande).

Dado que puedo cambiar la instrucción SQL para el orden basado en el Wilson anotar intervalo de la siguiente manera:

select 
    m.Name, m.Body 
from 
    Models as m 
     left outer join TagAssociations as ta on 
      ta.ModelTypeId = <fixed model type id> and 
      ta.ModelId = m.Id 
     left outer join Tags as t on t.Id = ta.TagId 
     left outer join VoteTallyStatistics as s on 
      s.ModelTypeId = ta.ModelTypeId and 
      s.ModelId = ta.ModelId 
where 
    t.Name = <tag> 
order by 
    --- Use Id to break ties. 
    s.WilsonIntervalLowerBound desc, m.Id 

Parece una elección fácil de usar esto para manejar la pieza de funcionalidad desbordamiento de pila   "llegar todos los elementos etiquetados con <tag> ".

Respuestas

Originalmente, pensé que esto está en un índice separado de su propia, con una clave de nuevo en el índice de Preguntas.

Creo que debe haber una combinación de cada modelo y cada respuesta (si hay una) para que las puntuaciones de relevancia en los diferentes modelos sean más "iguales" cuando se comparen entre sí.

Esto, por supuesto, inflaría el índice. Estoy algo cómodo con eso ahora mismo.

O, ¿hay alguna forma de almacenar, digamos, los modelos y respuestas como documentos individuales en Lucene.NET y luego tomar ambos y poder obtener el puntaje de relevancia para una consulta tratando ambos documentos como uno? Si es así, esto sería ideal.

Por supuesto, existe la pregunta de qué campos se almacenarán, indizarán, analizarán (¿todas las operaciones pueden ser operaciones separadas o mix-and-matching)? ¿Cuánto indexaría uno?

¿Qué pasa con el uso de stemmers/porters especiales para errores de ortografía (usando Metaphone) y sinónimos (hay terminología en la comunidad que daré servicio que tiene su propia jerga/terminología para ciertas cosas que tiene múltiples representaciones)?

Boost

Esto se relaciona con la indexación por supuesto, pero creo que merece su propia sección.

¿Está aumentando los campos y/o documentos? Si es así, ¿cómo los impulsas? ¿El impulso es constante para ciertos campos? O se vuelve a calcular para campos en los que se aplica el voto/vista/datos favoritos/externos.

Por ejemplo, en el documento, ¿el título recibe un impulso sobre el cuerpo? Si es así, ¿qué factores de impulso crees que funcionan bien? ¿Qué pasa con las etiquetas?

La idea aquí es la misma que en la línea de Stack   Overflow. Los términos en el documento tienen relevancia, pero si un documento está etiquetado con el término, o está en el título, entonces debe ser potenciado.

Shashikant Kore sugiere una estructura de documento como este:

  • Título
  • Pregunta
  • respuesta aceptada (O respuesta altamente votado si no hay respuesta aceptada)
  • Todas las respuestas combinado

Y luego usar el impulso pero no basado en el valor de voto sin procesar. Creo que tengo eso cubierto con el intervalo de puntuación de Wilson.

La pregunta es, ¿debería aplicarse el impulso a todo el documento? Me inclino por no en este caso, porque significaría que tendría que reindexar el documento cada vez que un usuario votara en el modelo.

Búsqueda de artículos etiquetados

principio pensé que al consultar una etiqueta (haciendo clic en concreto en uno o usando la estructura de URL para buscar contenido etiquetado), que es una TermQuery simple contra el índice de etiqueta para la etiqueta, luego en el índice de asociaciones (si es necesario) y luego de vuelta a las preguntas, Lucene.NET maneja esto muy rápidamente.

Sin embargo, teniendo en cuenta las notas anteriores sobre lo fácil que es hacer esto en SQL Server, he optado por esa ruta cuando se trata de buscar elementos etiquetados.

General Búsqueda

Así que ahora, la pregunta más sobresaliente es cuando se hace una frase general o término de búsqueda contra los contenidos, qué y cómo se puede integrar otra información (como votos) con el fin de determinar los resultados en el orden correcto? Por ejemplo, al realizar esta búsqueda en ASP.NET MVC on Stack Overflow, estos son los recuentos de los cinco mejores resultados (cuando se utiliza la pestaña relevancia):

q votes answers accepted answer votes asp.net highlights mvc highlights 
    ------- ------- --------------------- ------------------ -------------- 
     21  26     51     2    2 
     58  23     70     2    5 
     29  24     40     3    4 
     37  15     25     1    2 
     59  23     47     2    2 

Tenga en cuenta que los aspectos más destacados son sólo en el título y el resumen en la página de resultados y son solo indicadores menores en cuanto a cuál es la frecuencia del término verdadero en el documento, título, etiqueta, respuesta (sin importar cómo se apliquen, que es otra buena pregunta).

¿Cómo se combina todo esto?

En este punto, sé que Lucene.NET devolverá un puntaje de relevancia normalizado, y los datos de voto me darán un intervalo de puntuación de Wilson que puedo usar para determinar el puntaje de confianza.

¿Cómo debo considerar la combinación de dos puntajes para indicar el orden de clasificación del conjunto de resultados según la relevancia y la confianza?

Es obvio para mí que debería haber alguna relación entre los dos, pero esa relación debería ser evadida en este momento. Sé que tengo que refinarlo a medida que pasa el tiempo, pero realmente estoy perdido en esta parte.

Mis pensamientos iniciales son si la puntuación de relevancia es beween 0 y 1 y la puntuación de confianza está entre 0 y 1, entonces yo podría hacer algo como esto:

1/((e^cs) * (e^rs)) 

De esta manera, se obtiene un valor normalizado que se acerca a 0, el resultado es más relevante y seguro, y se puede ordenar sobre eso.

El problema principal es que si el refuerzo se realiza en la etiqueta o en el campo de título, entonces la puntuación de relevancia está fuera de los límites de 0 a 1 (el extremo superior se vuelve ilimitado y no sé cómo lidiar con eso).

Además, creo que tendré que ajustar el puntaje de confianza para dar cuenta de los votos que son completamente negativos. Dado que los conteos de votos que son completamente negativos dan como resultado un intervalo de puntuación de Wilson con un límite inferior de 0, algo con -500 votos tiene el mismo puntaje de confianza que algo con -1 voto, o 0 votos.

Afortunadamente, el límite superior disminuye de 1 a 0 a medida que aumentan los votos negativos. Podría cambiar la puntuación de confianza que haya un rango de -1 a 1, así:

confidence score = votetally < 0 ? 
    -(1 - wilson score interval upper bound) : 
    wilson score interval lower bound 

El problema con esto es que enchufar 0 en la ecuación alineará todos los elementos con cero votos por debajo de los que tienen votos negativos.

Para ese fin, estoy pensando que si el puntaje de confianza va a ser usado en una ecuación recíproca como la anterior (me preocupa el desbordamiento obviamente), entonces debe ser modificado para que siempre sea positivo. Una forma de lograr esto es:

confidence score = 0.5 + 
    (votetally < 0 ? 
     -(1 - wilson score interval upper bound) : 
     wilson score interval lower bound)/2 

Mis otras preocupaciones son cómo realizar el cálculo realidad dada Lucene.NET y SQL Server. Dudo en poner el puntaje de confianza en el índice de Lucene porque requiere el uso del caché de campo, lo que puede tener un gran impacto en el consumo de memoria (como se mencionó anteriormente).

Una idea que tuve fue obtener el puntaje de relevancia de Lucene.NET y luego usar un table-valued parameter para transmitir el puntaje a SQL Server (junto con los identificadores de los elementos a seleccionar), en ese punto realizaría el cálculo con el puntaje de confianza y luego devolver los datos debidamente ordenados.

Como dije antes, hay muchas otras preguntas que tengo sobre esto, y las respuestas han comenzado a enmarcar las cosas, y seguirán ampliándose a medida que la pregunta y las respuestas mejoren.

Respuesta

2

Probablemente haya pensado más sobre este tema que la mayoría de las personas que intentarán responderle (parte de la razón por la que ha pasado un día y soy su primera respuesta, me imagino). Voy a tratar de abordar tus últimas tres preguntas, porque hay muchas en las que no tengo tiempo para entrar, y creo que esas tres son las más interesantes (las preguntas de implementación física probablemente se desarrollen). para terminar siendo 'elegir algo, y luego ajustarlo a medida que aprendes más').

voto No estoy seguro de que los votos hagan algo más relevante para una búsqueda, francamente, simplemente los hace más populares. Si eso tiene sentido, estoy tratando de decir que si una publicación determinada es relevante para su pregunta es, en su mayoría, independiente de si fue relevante para otras personas. Dicho esto, probablemente haya al menos una correlación débil entre las preguntas interesantes y las que la gente querría encontrar. Los datos de votación probablemente sean más útiles para realizar búsquedas basadas puramente en datos, p. búsquedas de tipo "más popular".En las búsquedas genéricas basadas en texto, probablemente no le daría ningún peso a los votos al principio, pero consideraría trabajar en un algoritmo que tal vez proporcione un ligero peso para la clasificación (por lo tanto, no se devuelven los resultados, sino un impulso menor al pedido). de ellos).

answers Estoy de acuerdo con su enfoque aquí, sujeto a algunas pruebas; recuerde que esto va a tener que ser un proceso iterativo basado en comentarios de los usuarios (por lo que necesitará para recoger las métricas de si las búsquedas devuelven resultados exitosos para el buscador)

otra No se olvide de la puntuación del usuario también . Por lo tanto, los usuarios obtienen puntos en SO también, y eso influye en su rango predeterminado en las respuestas de cada pregunta que responden (parece que es principalmente para desempate en respuestas que tienen el mismo número de protuberancias)

+0

@Paul: He actualizado la pregunta para reflejar cómo los datos de votación (que es un puntaje de confianza) se relacionan con la puntuación de relevancia, así como pensamientos sobre respuestas No creo que vaya a utilizar la reputación del usuario para evaluar los resultados de clasificación de búsqueda, pero en términos de respuestas de desempate en términos de votos, es bastante fácil hacerlo en SQL Server. – casperOne

2

Determinar la relevancia siempre es complicado. Necesitas descubrir lo que estás tratando de lograr. ¿Su búsqueda intenta proporcionar una coincidencia exacta para un problema que alguien podría tener o está tratando de proporcionar una lista de artículos recientes sobre un tema?

Una vez que haya calculado lo que desea devolver, puede ver el efecto relativo de cada característica que está indexando. Eso va a tener una búsqueda difícil. A partir de ahí, modifica según los comentarios de los usuarios (sugiero usar comentarios implícitos en lugar de explícitos, de lo contrario molestarás al usuario).

En cuanto a la indexación, debe tratar de poner los datos para que cada elemento tenga toda la información necesaria para clasificarlo. Esto significa que tendrás que tomar los datos de varias ubicaciones para crearlos. Algunos sistemas de indexación tienen la capacidad de agregar valores a los elementos existentes, lo que facilitaría la adición de puntajes a las preguntas cuando aparecieran respuestas posteriores. La simplicidad simplemente haría que reconstruyese la pregunta cada cierto tiempo.

10

Las respuestas que estás buscando realmente no se pueden encontrar solo con lucene. Necesita algoritmos de clasificación y agrupamiento para filtrar y comprender los datos y cómo se relacionan. Lucene puede ayudarlo a obtener datos normalizados, pero luego necesita el algoritmo correcto.

le recomiendo que echa un vistazo a uno o todos de los siguientes libros, que le ayudará con las matemáticas y conseguir que apunta en la dirección correcta:

Algorithms of the Intelligent Web

Collective Intelligence in Action

Programming Collective Intelligence

+0

Mike Glenn: Haces un muy buen punto. Voy a actualizar la pregunta para reflejar ese hecho más adelante en el día, por lo que su opinión sobre la pregunta actualizada sería apreciada. Además, leí "Programming Collective Intelligence" (y lo consulté antes de escribir esto) y descubrí que no ayuda mucho en esta situación (donde tienes algún tipo de puntaje de relevancia vs.clasificación del artículo que es relevante), pero probablemente lo eche un segundo vistazo. – casperOne

+0

Algoritmos de la Web inteligente, es un libro que realmente va a querer verificar. En cuanto a la pregunta, aquí está cómo comenzaría a usar lucene. El texto de la pregunta se colocaría en un campo tokenizado, lo mismo con las respuestas, los comentarios y las etiquetas en sus propios campos en el documento. Por defecto lucene pondera las coincidencias en campos con menos términos que una coincidencia en un campo con muchos términos. Lo que quiere decir que una coincidencia en el campo de etiquetas tendrá más relevancia que una coincidencia en los campos de pregunta o respuesta. –

+0

Ahora trayendo los votos y posiblemente la puntuación de los representantes de los usuarios PODRÍA hacer su búsqueda más precisa. Pero necesitaría establecer una prueba aleatorizada y determinar una forma de medir la efectividad de ambos métodos para entregar el resultado que los usuarios estaban buscando. –

2

Creo que Lucene no es bueno para este trabajo. Necesita algo realmente rápido con alta disponibilidad ... como SQL ¿Pero quiere código abierto?

Le sugiero que use Sphinx - http://www.sphinxsearch.com/ Es mucho mejor, y estoy hablando con experiencia, los usé a los dos.

Sphinx es increíble. Realmente es.

+0

@Yuki: Cabe señalar que estoy usando SQL Server 2008 en el back-end, por lo que Sphinx no es útil. – casperOne

+0

Hola de nuevo, ¡Bien, estás equivocado! ¡Utilicé Sphinx con Sql Server 2008 (e incluso 2005)! Al configurarlo, puede especificar la conexión y la instrucción de selección en los archivos ini de índice ... A Sphinx no le importa qué base de datos se utiliza para obtener datos. Busque en Google y puede encontrar algunos ejemplos. – Yuki

+0

Disculpe, tiene razón, funcionará con SQL Server 2008, pero también estoy en un entorno de alojamiento compartido, por lo que no puedo ejecutar un servicio (que creo que es obligatorio). – casperOne

4

El índice Lucene tendrá siguientes campos:

  • Título
  • Pregunta
  • respuesta aceptada (o la respuesta altamente votado si no hay respuesta aceptada)
  • Todas las respuestas combinado

Todos estos son campos que se analizan. La normalización de longitud está desactivada para obtener un mejor control en la puntuación.

El orden antes mencionado de los campos también refleja su importancia en orden descendente. Es decir, si la coincidencia de consulta en el título es más importante que en la respuesta aceptada, todo lo demás permanece igual.

El número de votos positivos es para la pregunta y la respuesta principal se puede capturar mediante el aumento de esos campos. Sin embargo, el recuento de votos acumulados sin procesar no se puede usar como valores de impulso, ya que podría sesgar los resultados dramáticamente. (Una pregunta con 4 votos ascendentes obtendrá el doble del puntaje de uno con 2 votos hacia arriba.) Estos valores deben ser amortiguados agresivamente antes de que puedan ser utilizados como factor de impulso. Usar algo del logaritmo natural (para votos ascendentes> 3) se ve bien.

El título se puede aumentar con un valor un poco más alto que el de la pregunta.

Aunque la interconexión de preguntas no es muy común, tener un peso básico similar a un pagerank para una pregunta podría arrojar algunos resultados interesantes.

No considero las etiquetas de la pregunta como información muy valiosa para la búsqueda. Las etiquetas son agradables cuando solo quieres navegar por las preguntas. La mayoría de las veces, las etiquetas son parte del texto, por lo que la búsqueda de las etiquetas coincidirá con la pregunta. Esto está abierto a discusión, sin embargo.

Se realizará una consulta de búsqueda típica en los cuatro campos.

+(title:query question:query accepted_answer:query all_combined:query) 

Esto es un bosquejo amplio y requerirá de sintonía significativa para llegar a los valores correctos a impulsar y pesos adecuados para las consultas, si es necesario. La experiencia mostrará los pesos adecuados para las dos dimensiones de calidad: relevancia e importancia. Puede complicar las cosas introduciendo recencia como un parámetro de cambio. La idea aquí es que, si ocurre un problema en una versión particular del producto y se corrige en revisiones posteriores, las nuevas preguntas podrían ser más útiles para el usuario.

Se pueden agregar algunos giros interesantes para buscar. Alguna forma de búsqueda básica de sinónimos podría ser útil si solo se encuentran unos "pocos" resultados coincidentes. Por ejemplo, "descrease java heap size" es lo mismo que "reducir el tamaño del montón de Java". Pero, entonces, también significará que la "reducción del mapa" comenzará a coincidir con la "disminución del mapa". (El corrector ortográfico es obvio, pero supongo que los programadores deletrearían sus consultas correctamente.)

+0

@Shashikant Kore: ¿Sería mejor impulsar en el nivel de consulta o en el nivel de documento/campo? Creo que podría ser mejor en el campo o en el nivel de consulta, ya que creo que quiero ponderar la puntuación de relevancia de forma diferente en función de los cambios a la pregunta que hice anteriormente. – casperOne

+0

Sí, mi preferencia es para aumentar el nivel de campo, como se sugirió anteriormente. Como ya tenemos información de voto en el momento de la indexación, es una buena idea usarla en ese momento. –

Cuestiones relacionadas