Нужен совет по оптимизации запросов Lucene

StackOverflow https://stackoverflow.com/questions/406161

  •  03-07-2019
  •  | 
  •  

Вопрос

Я работаю над веб-приложением для поиска работы с использованием Lucene.Пользователь на моем сайте может искать вакансии, которые находятся в радиусе 100 миль, скажем, от "Бостона, Массачусетс" или любого другого места.Кроме того, мне нужно показать результаты поиска, отсортированные по "релевантности" (т.е.Оценка, возвращенная lucene) в порядке убывания.

Я использую сторонний API для получения всех городов в пределах заданного радиуса города.Этот API возвращает мне около 864 городов в радиусе 100 миль от "Бостона, Массачусетс".

Я создаю запрос Lucene для города / штата, используя следующую логику, которая является частью моего метода "BuildNearestCitiesQuery".Здесь nearestCities - это хэш-таблица, возвращаемая вышеупомянутым API.Она содержит 864 города с ключом CityName ass и кодом состояния в качестве значения.А finalQuery - это объект Lucene BooleanQuery, который содержит другие критерии поиска, введенные пользователем, такие как: навыки, ключевые слова и т.д.

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

Затем я ввожу объект finalQuery в метод поиска Lucene, чтобы получить все задания в радиусе 100 миль.:

searcher.Search(finalQuery, collector);

Я обнаружил, что выполнение этого метода BuildNearestCitiesQuery занимает в среднем целых 29 секунд, что, очевидно, неприемлемо по любым стандартам веб-сайта.Я также обнаружил, что выполнение инструкций, включающих "Синтаксический анализ", занимает значительное количество времени по сравнению с другими инструкциями.

Задание для данного местоположения является динамическим атрибутом в том смысле, что в городе может быть 2 задания (соответствующие определенному критерию поиска) сегодня, но ноль заданий для тех же критериев поиска через 3 дня.Таким образом, я не могу использовать здесь какое-либо "Кэширование".

Есть ли какой-нибудь способ оптимизировать эту логику? или, если уж на то пошло, весь мой подход / алгоритм к поиску всех заданий в радиусе 100 миль с использованием Lucene?

К вашему сведению, вот как выглядит моя индексация в 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));

Огромное спасибо за чтение!Я был бы очень признателен вам за помощь в этом.

Дженис

Это было полезно?

Решение

Не совсем уверен, что я полностью понимаю ваш код, но когда дело доходит до геопространственного поиска, подход с фильтром может быть более подходящим.Может быть, эта ссылка подскажет вам несколько идей - http://sujitpal.blogspot.com/2008/02/spatial-search-with-lucene.html

Может быть, вы сможете использовать Фильтрs также и для других частей вашего запроса.Честно говоря, ваш запрос выглядит довольно сложным.

--Выносливый

Другие советы

Помимо tempFinalQuery поскольку код, который вы публикуете, не используется и не требует поиска по карте для получения состояния, кажется, что в нем нет ничего слишком вопиющего.Помимо форматирования...

Если все время тратится на Parse методы, размещение их кода здесь имело бы смысл.

Возможно, я упустил суть вашего вопроса, но есть ли у вас возможность сохранить широту и долготу для почтовых индексов?Если это возможно, вы могли бы затем вычислить расстояние между двумя координатами, обеспечив гораздо более простой показатель оценки.

Я считаю, что лучший подход - переместить определение ближайшего города в фильтр поиска.Я бы также пересмотрел способ настройки поля у вас;рассмотрите возможность создания одного термина, который содержит город + штат, чтобы упростить запрос.

Я бы предложил:

  • сохранение широты и долготы местоположений по мере их поступления
  • когда пользователь вводит город и расстояние, преобразуйте их в значение широты и lon в градусах
  • выполните один простой поиск на основе числовых сравнений расстояний lat / lon

Вы можете увидеть пример того, как это работает, в Гео::Расстояние Модуль Perl.Взгляните на closest метод в Источник, который реализует этот поиск с помощью простого SQL.

Согласитесь с остальными присутствующими, что это слишком сильно пахнет.Кроме того, выполнение текстового поиска по названиям городов не всегда настолько надежно.В названиях мест часто присутствует некоторая субъективность (особенно районов внутри города, которые сами по себе могут быть большими).

Выполнение геопространственного запроса - это правильный путь.Не зная остальной части вашей настройки, трудно что-то советовать.У вас есть пространственная поддержка, встроенная в Fluent для NHibernate и, например, в SQL Server 2008.Затем вы могли бы выполнить поиск очень быстро и эффективно.Однако ваша задача состоит в том, чтобы заставить это работать в Lucene.

Возможно, вы могли бы выполнить запрос "первого прохождения", используя поддержку spatial в SQL Server, а затем запустить эти результаты через Lucene?

Другим важным преимуществом выполнения пространственных запросов является то, что затем вы можете легко сортировать результаты по расстоянию, что выгодно для ваших клиентов.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top