Question

Je travaille sur une application de recherche d'emploi basée sur le Web et utilisant Lucene.L'utilisateur sur mon site peut rechercher des emplois se trouvant dans un rayon de 100 milles autour de "Boston, MA". ou tout autre endroit. De plus, je dois afficher les résultats de la recherche triés par "pertinence" (c'est-à-dire le score renvoyé par lucene) dans l'ordre décroissant.

J'utilise une API tierce pour rechercher toutes les villes situées dans un rayon donné d'une ville. Cette API me renvoie environ 864 villes situées dans un rayon de 100 miles autour de "Boston, MA".

Je construis la requête ville / état Lucene en utilisant la logique suivante, qui fait partie de ma "BuildNearestCitiesQuery". méthode. Ici, nearCities est une table de hachage renvoyée par l'API ci-dessus. Elle contient 864 villes avec la clé CityName ass et le StateCode comme valeur. Et finalQuery est un objet Lucene BooleanQuery qui contient d’autres critères de recherche entrés par l’utilisateur, tels que: compétences, mots-clés, 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);

J'ai ensuite saisi l'objet finalQuery dans la méthode de recherche de Lucene pour obtenir tous les travaux dans un rayon de 100 miles.:

searcher.Search(finalQuery, collector);

J'ai découvert que cette méthode BuildNearestCitiesQuery prend 29 secondes en moyenne, ce qui est évidemment inacceptable pour tous les sites Web. J'ai également découvert que les déclarations impliquant "Parse" prend beaucoup de temps à exécuter par rapport aux autres instructions.

Un travail pour un lieu donné est un attribut dynamique dans le sens où une ville pourrait avoir 2 emplois (répondant à un critère de recherche particulier) aujourd'hui, mais aucun travail pour les mêmes critères de recherche après 3 jours. Donc, je ne peux en utiliser aucun. "Mise en cache" par ici.

Y a-t-il un moyen d’optimiser cette logique ou d’autre part mon approche / algorithme complet pour rechercher tous les emplois dans un rayon de 100 km avec Lucene?

Pour info, voici à quoi ressemble mon indexation dans 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));

Merci beaucoup pour votre lecture! J'apprécierais vraiment votre aide à ce sujet.

Janis

Était-ce utile?

La solution

Je ne suis pas certain de bien comprendre votre code, mais s’agissant de la recherche géospatiale, une approche de filtre pourrait être plus appropriée. Peut-être que ce lien peut vous donner quelques idées - http: // sujitpal .blogspot.com / 2008/02 / recherche-spatiale-avec-lucene.html

Vous pouvez également utiliser des filtres pour d'autres parties de votre requête. Pour être honnête, votre requête a l'air assez complexe.

- Hardy

Autres conseils

Hormis le fait que tempFinalQuery soit inutilisé et une recherche de carte inutile pour obtenir l'état, il ne semble pas y avoir de contenu trop flagrant dans le code que vous publiez. En dehors de la mise en forme ...

Si tout le temps est pris dans les méthodes Parse , il serait logique de poster leur code ici.

J'ai peut-être manqué le sens de votre question, mais avez-vous la possibilité de stocker la latitude et la longitude pour les codes postaux? Si cela est une option, vous pouvez alors calculer la distance entre deux coordonnées en fournissant une métrique de score beaucoup plus simple.

Je pense que la meilleure approche consiste à déplacer la détermination de la ville la plus proche dans un filtre de recherche. Je voudrais également reconsidérer comment vous avez la configuration sur le terrain; Envisagez de créer un terme comportant la mention ville + état afin de simplifier la requête.

Je suggérerais:

  • stocker la latitude et la longitude des lieux au fur et à mesure qu'ils entrent
  • lorsqu'un utilisateur entre une ville et une distance, transformez-la en une valeur lat / lon et en degrés
  • faire une seule recherche simple basée sur des comparaisons de distance numérique lat / lon

Vous pouvez voir un exemple de ce fonctionnement dans Geo :: Distance Module Perl. Examinez la méthode la plus proche dans source , qui implémente cette recherche via SQL simple.

Convenez avec les autres ici que cela sent trop. Effectuer une recherche textuelle sur les noms de ville n’est pas toujours aussi fiable. Il y a souvent un peu de subjectivité entre les noms de lieux (en particulier les zones d'une grande ville qui pourraient être grandes).

Faire une requête géo-spatiale est la voie à suivre. Ne sachant pas le reste de votre installation, il est difficile de vous conseiller. Vous avez un support Spatial intégré dans Fluent to NHibernate, et SQL Server 2008 par exemple. Vous pouvez ensuite effectuer une recherche très rapidement et efficacement. Cependant, votre défi est de faire en sorte que cela fonctionne au sein de Lucene.

Vous pouvez éventuellement effectuer un "premier passage". requête utilisant le support spatial dans SQL Server, puis exécuter ces résultats via Lucene?

L’autre avantage majeur des requêtes spatiales est que vous pouvez ensuite facilement trier vos résultats par distance, ce qui représente un avantage pour vos clients.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top