Pergunta

Am trabalhando em aplicativo de pesquisa Job baseado na web usando Lucene.User no meu site pode procurar por empregos que estão dentro de um raio de 100 milhas de dizer "Boston, MA" ou qualquer outro local. Além disso, eu preciso mostrar os resultados da pesquisa classificado por "relevância" (ie. Score retornado por lucene) em ordem decrescente.

Eu estou usando um terceiro partido API para buscar todas as cidades dentro de determinado raio de um Cidade.Esta API retorna me cerca de 864 cidades no raio de 100 milhas raio de "Boston, MA".

Estou construindo a consulta Lucene cidade / estado usando a seguinte lógica que faz parte do meu método "BuildNearestCitiesQuery". Aqui nearestCities é um hashtable retornado pelo API.It acima contém 864 cidades com CityName ass chave e StateCode como valor. E FINALQUERY é um objeto Lucene BooleanQuery que contém outros critérios de pesquisa inseridos pelo usuário, como:. Habilidades, palavras-chave, 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);

Eu objeto FINALQUERY depois de entrada para o método de pesquisa do Lucene para obter todos os trabalhos dentro de 100 milhas de raio:.

searcher.Search(finalQuery, collector);

Eu descobri este método BuildNearestCitiesQuery leva uma gritante 29 segundos em média para executar o que obviamente é inaceitável por qualquer padrão de um website.I também descobriu que as declarações que envolvem "Parse" levar uma quantidade considerável de tempo para executar como em comparação com outras declarações.

Um trabalho para um determinado local é um atributo dinâmico no sentido de que uma cidade pode ter 2 empregos (uma reunião de determinados critérios de pesquisa) hoje, mas de zero trabalho para os mesmos critérios de pesquisa após 3 days.So, eu não posso usar qualquer "cache" por aqui.

Existe alguma maneira eu posso otimizar essa lógica? Ou para essa matéria toda a minha abordagem / algoritmo para encontrar todos os trabalhos dentro de 100 milhas usando Lucene?

FYI, aqui é como minha indexação no Lucene parece com:

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));

Graças a tonelada para leitura! Eu realmente aprecio a sua ajuda sobre isso.

Janis

Foi útil?

Solução

Não tem a certeza se eu entendo completamente seu código, mas quando se trata de geoespaciais procurar uma abordagem filtro pode ser mais apropriado. Talvez este link pode lhe dar algumas idéias - http: // sujitpal .blogspot.com / 2008/02 / espaço-procurar-com-lucene.html

Talvez você possa usar Filtro s para outras partes da sua consulta, bem. Para ser honesto sua aparência de consulta bastante complexa.

- Hardy

Outras dicas

Além de tempFinalQuery sendo inutilizados e um mapa de pesquisa desnecessária para obter o estado, não parece ser nada muito chocante no código que você postar. Além da formatação ...

Se o tempo é tomado nos métodos Parse, postando seu código aqui faria sentido.

eu poderia ter perdido o ponto de sua pergunta, mas você tem a possibilidade de armazenar latitude e longitude para zip códigos? Se isso é uma opção, você poderia, então, calcular a distância entre duas coordenadas fornecendo uma pontuação muito mais simples métrica.

Eu acredito que a melhor abordagem é mover a determinação da cidade mais próxima em um filtro de pesquisa. Também gostaria de reconsiderar como você tem a configuração de campo; considerar a criação de um termo que tem cidade + estado para que simplificaria a consulta.

Eu sugiro:

  • armazenar a latitude ea longitude de locais como eles vêm em
  • quando um usuário digita uma cidade e distância, transformar isso em uma latitude / longitude valor e graus
  • não um único, pesquisa simples baseada na distância numérica lat / lon comparações

Você pode ver um exemplo de como isso funciona na Geo :: Distância módulo Perl. Dê uma olhada no método closest no fonte , que implementa esta pesquisa via simples SQL.

Concordo com os outros aqui que isto cheira muito. Também fazendo uma pesquisa textual em nomes de cidades nem sempre é tão confiável. Muitas vezes há um pouco de subjetividade entre nomes de lugares (especialmente áreas dentro de uma cidade que poderia em si ser grande).

Fazendo uma consulta espacial geo é o caminho a percorrer. Não sabendo o resto de sua configuração é difícil aconselhar. Você tem suporte espacial construído em Fluent NHibernate, e SQL Server 2008, por exemplo. Você poderia, então, fazer uma pesquisa muito forma rápida e eficiente. No entanto, o desafio é para começar este trabalho dentro Lucene.

Você poderia fazer uma consulta de "primeira passagem" usando suporte espacial no SQL Server, e em seguida, executar esses resultados através Lucene?

A outra grande vantagem de fazer consultas espaciais é que você pode, então, facilmente classificar os resultados por distância que é uma vitória para os seus clientes.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top