Pregunta

Estoy trabajando en la aplicación de búsqueda de empleo basada en la web usando Lucene. El usuario en mi sitio puede buscar trabajos que estén dentro de un radio de 100 millas de, digamos, Boston, MA o cualquier otro lugar. Además, necesito mostrar los resultados de búsqueda ordenados por "relevancia" (es decir, puntuación devuelta por lucene) en orden descendente.

Estoy usando una API de terceros para obtener todas las ciudades dentro del radio dado de una ciudad. Esta API me devuelve alrededor de 864 ciudades dentro de un radio de 100 millas de "Boston, MA".

Estoy construyendo la consulta de Lucene de ciudad / estado usando la siguiente lógica que es parte de mi " BuildNearestCitiesQuery " método. Aquí closestCities es una tabla hash devuelta por la API anterior. Contiene 864 ciudades con la clave de asilo CityName y StateCode como valor. Y finalQuery es un objeto Lucene BooleanQuery que contiene otros criterios de búsqueda ingresados ??por el usuario como: habilidades, palabras clave, etc.

foreach (string city in nearestCities.Keys)

{

    BooleanQuery tempFinalQuery = finalQuery;

    cityStateQuery = new BooleanQuery();    

    queryCity = queryParserCity.Parse(city);

    queryState = queryParserState.Parse(((string[])nearestCities[city])[1]);

    cityStateQuery.Add(queryCity, BooleanClause.Occur.MUST); //must is like an AND

    cityStateQuery.Add(queryState, BooleanClause.Occur.MUST);

} 


nearestCityQuery.Add(cityStateQuery, BooleanClause.Occur.SHOULD); //should is like an OR



finalQuery.Add(nearestCityQuery, BooleanClause.Occur.MUST);

Luego ingrese el objeto finalQuery en el método de búsqueda de Lucene para obtener todos los trabajos dentro de un radio de 100 millas:

searcher.Search(finalQuery, collector);

Descubrí que este método de BuildNearestCitiesQuery toma la friolera de 29 segundos en un promedio de ejecución, lo que obviamente es inaceptable según los estándares de un sitio web. También descubrí que las declaraciones que implican " Parse " tomar una cantidad considerable de tiempo para ejecutar en comparación con otras declaraciones.

Un trabajo para una ubicación dada es un atributo dinámico en el sentido de que una ciudad podría tener 2 trabajos (que cumplan con un criterio de búsqueda particular) hoy, pero cero trabajo para el mismo criterio de búsqueda después de 3 días. Por lo tanto, no puedo usar ninguno " Almacenamiento en caché " por aquí.

¿Hay alguna forma de optimizar esta lógica? ¿O para todo mi enfoque / algoritmo completo para encontrar todos los trabajos dentro de 100 millas usando Lucene?

Para tu información, aquí está cómo se ve mi indexación en Lucene:

doc.Add(new Field("jobId", job.JobID.ToString().Trim(), Field.Store.YES, Field.Index.UN_TOKENIZED));

doc.Add(new Field("title", job.JobTitle.Trim(), Field.Store.YES, Field.Index.TOKENIZED));

doc.Add(new Field("description", job.JobDescription.Trim(), Field.Store.NO, Field.Index.TOKENIZED));

doc.Add(new Field("city", job.City.Trim(), Field.Store.YES, Field.Index.TOKENIZED , Field.TermVector.YES));

doc.Add(new Field("state", job.StateCode.Trim(), Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.YES));

doc.Add(new Field("citystate", job.City.Trim() + ", " + job.StateCode.Trim(), Field.Store.YES, Field.Index.UN_TOKENIZED , Field.TermVector.YES));

doc.Add(new Field("datePosted", jobPostedDateTime, Field.Store.YES, Field.Index.UN_TOKENIZED));

doc.Add(new Field("company", job.HiringCoName.Trim(), Field.Store.YES, Field.Index.TOKENIZED));

doc.Add(new Field("jobType", job.JobTypeID.ToString(), Field.Store.NO, Field.Index.UN_TOKENIZED,Field.TermVector.YES));

doc.Add(new Field("sector", job.SectorID.ToString(), Field.Store.NO, Field.Index.UN_TOKENIZED, Field.TermVector.YES));

doc.Add(new Field("showAllJobs", "yy", Field.Store.NO, Field.Index.UN_TOKENIZED));

¡Muchas gracias por leer! Realmente agradecería su ayuda en esto.

Janis

¿Fue útil?

Solución

No estoy seguro si entiendo completamente su código, pero cuando se trata de búsqueda geoespacial, un enfoque de filtro podría ser más apropiado. Tal vez este enlace pueda darle algunas ideas: http: // sujitpal .blogspot.com / 2008/02 / spatial-search-with-lucene.html

Tal vez también pueda usar Filtro para otras partes de su consulta. Para ser sincero, su consulta parece bastante compleja.

--Hardy

Otros consejos

Aparte de que tempFinalQuery no se usa y una búsqueda de mapa innecesaria para obtener el estado, no parece haber nada demasiado atroz en el código que publica. Aparte del formateo ...

Si se toma todo el tiempo en los métodos Parse , publicar su código aquí tendría sentido.

Es posible que me haya perdido el punto de su pregunta, pero ¿tiene la posibilidad de almacenar la latitud y la longitud de los códigos postales? Si esa es una opción, podría calcular la distancia entre dos coordenadas proporcionando una métrica de puntuación mucho más sencilla.

Creo que el mejor enfoque es mover la determinación de la ciudad más cercana a un filtro de búsqueda. También reconsideraría cómo tiene la configuración de campo; considere crear un término que tenga ciudad + estado para simplificar la consulta.

sugeriría:

  • almacenar la latitud y longitud de los lugares a medida que entran
  • cuando un usuario ingresa una ciudad y una distancia, conviértalo en un valor de lat / lon y grados
  • realice una búsqueda simple y simple basada en comparaciones numéricas de lat / lon de distancia

Puede ver un ejemplo de cómo funciona esto en Geo :: Distance Módulo Perl. Eche un vistazo al método más cercano en el source , que implementa esta búsqueda a través de SQL simple.

De acuerdo con los demás aquí, esto huele demasiado. También hacer una búsqueda textual de nombres de ciudades no siempre es tan confiable. A menudo hay un poco de subjetividad entre los nombres de lugares (particularmente áreas dentro de una ciudad que en sí mismas podrían ser grandes).

Hacer una consulta geoespacial es el camino a seguir. No saber el resto de su configuración es difícil de aconsejar. Tiene compatibilidad espacial integrada en Fluent to NHibernate y SQL Server 2008, por ejemplo. Luego puedes hacer una búsqueda muy de forma rápida y eficiente. Sin embargo, tu reto es conseguir que esto funcione dentro de Lucene.

Podrías hacer una " primera pasada " consulta usando soporte espacial en SQL Server, y luego ejecuta esos resultados a través de Lucene?

El otro beneficio importante de hacer consultas espaciales es que puede ordenar fácilmente sus resultados por distancia, lo que es una ganancia para sus clientes.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top