2008-10-24 3 views
38

Мне очень хотелось бы знать, как теги и поиск Stack Overflow архивируются, потому что это работает очень хорошо.Оптимальная архитектура данных для тегов, облаков и поиска (например, StackOverflow)?

Что такое хорошая база/модель поиска, если я хочу сделать все следующие:

  1. Запоминание Метки на различных сущностей, (как нормированная т.е. Entity, Tag и Entity_Tag таблицы?)
    • Поиск объектов с определенными тегами
    • Построение облако тегов всех тегов, которые применяются к определенному результату поиска набор
    • Как показать список тегов для каждого элемента в результатах поиска?

Возможно, имеет смысл хранить тег в нормализованном виде, но и в качестве пространства-разделителей строки для целей # 2, # 4, и, возможно, # 3. Мысли?

Я слышал, что он сказал, что Stack Overflow использует Lucene для поиска. Это правда? Я слышал пару подкастов, обсуждавших оптимизацию SQL, но ничего о Lucene. Если они используют Lucene, мне интересно, сколько из результатов поиска происходит от Lucene, и есть ли облако тегов «сверла» вниз от Lucene.

ответ

5

Я не знаю, соответствуют ли они как оптимальные, но оба DotNetKicks и Kigg являются реализациями с открытым исходным кодом digg. Вы можете посмотреть, как они делают теги и поиск.

Мои лучшие догадки, не много дискуссий :)

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

Таким образом, мой первоначальный взнос, вероятно, является сущностью -> EntityTag < - тег.

  1. Этот подход позволяет легко находить элементы через тег, присоединяться к EntityTag, называть его днем.

  2. Для выбора отдельных тегов для набора результатов вам потребуется дополнительная операция. Итак, a.) Вытащите результирующий набор, б.) Нормализуйте пространство тегов. Я думаю, что вы делаете это независимо от того, что ответ на # 1 - даже набивка тегов в одно поле будет по-прежнему давать повторяющиеся теги (и вы должны десериализовать их для выполнения этой операции - так что больше работы, еще один аргумент для полностью реляционного подход).

  3. Все еще легко. Вот одна из областей, где сериализованный подход работает лучше. Не нужно присоединяться к дочерним тегам, это прямо в Entity. Тем не менее, вытаскивание тэгов 0..n через объединение двух таблиц не кажется мне слишком сложным. Если вы говорите о первоочередных соображениях, сначала создайте его, а затем оптимизируйте с помощью кеша или денорма.

Другой вариант - «сделать оба».Это похоже на преждевременную оптимизацию, но вы можете сделать полный нормализованный подход для поддержки любых операций, ориентированных на тег, и сериализации, чтобы продолжать иметь денормализованную версию прямо в Entity. Немного больше работы, некоторый потенциал, чтобы выпасть из синхронизации, если не полностью охвачены, но лучше всего из двух миров, если есть реальные ограничения на полностью нормализованный путь в ваших случаях использования.

Lucene также интересен, вы можете объявить конкретные метаданные в индексах IIRC, чтобы вы могли потенциально использовать поиск тегов таким же образом. Мое подозрение в том, что если вы заходите слишком далеко по этому пути, то в конечном итоге у вас будут некоторые отключения между тем, что вы храните в базе данных и индексом в какой-то момент. Я могу говорить выгодно о Lucene, он очень удобен и прост в использовании - я считаю .Text использовал его для своих возможностей поиска, и он поддерживал весь weblogs.asp.net до перехода на сервер сообщества. Я придерживаюсь этого для полнотекстового поиска, если MSSQL не находится в изображении/достаточен, разрешите проблемы с тегами в базе данных imo.

57

Wow Я просто написал большой пост и SO задохнулся и повесил на него, и когда я нажал кнопку «Назад», чтобы повторно отправить, редактор разметки был пуст. Aaargh.

Так вот я снова иду ...

Что касается переполнения стека, то получается, что они используют SQL server 2005 full text search.

Что касается проектов ОС, рекомендованных @Grant:

  • * DotNetKicks использует базу данных для мечения и Lucene для полнотекстового поиска. Кажется, что нет возможности комбинировать полнотекстовый поиск с поиском тегов.
  • Kigg использует Linq-to-SQL для запросов поиска и тегов. Оба запроса объединяются в Stories-> StoryTags-> Tags.
  • Оба проекта имеют 3 стола подход к мечения, как и все в целом, кажется, рекомендуют

Я также нашел некоторые другие вопросы на SO, что я пропустил раньше:

Что я сейчас делаю для каждого из элементов, которые я упоминал:

  1. В БД, 3 таблицы: Entity, Tag, Entity_Tag. Я использую БД для:
    • Построение сайтов шириной облака тегов
    • Поиск по тегам (т.е. URLs как так в /questions/tagged/ASP.NET)
  2. Для поиска я использую Lucene + NHibernate.Поиск
    • Метки concat'd в TagString, который индексируется Lucene
      • Так что я имею полную мощность двигателя запроса Lucene (AND/OR/NOT запросы)
      • я могу найти текст и фильтра тегов одновременно
      • анализатор Lucene сливает слова для лучшего поиска меток (т.е. поиск метки для «теста» будет также найти материал меченого «тестирование»)
    • Lucene возвращает потенциально огромный набор результатов, которые я постраничной 20 результатов
    • Тогда NHibernate загружает результат Сущности от Id, либо из БД или кэш Entity
    • Так что вполне возможно, что результаты поиска в 0 просмотров к БД
  3. не делать этого, но я думаю, что я, вероятно, буду пытаться найти способ, чтобы построить облако тегов из TagString в Lucene, а не взять другую БД удара
  4. не сделал этого но все же, но я, вероятно, буду хранить TagString в БД, чтобы я мог показать список тегов Entity без необходимости делать еще 2 соединения.

Это означает, что всякий раз, когда теги Субъект модифицируются, я должен:

  • Вставьте любые новые слова, которые уже не существуют
  • Insert/Delete из таблицы EntityTag
  • Update Entity .TagString
  • Обновить индекс Lucene для Entity

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

Время покажет ...

+0

косяка upmod этого поста достаточно – Shawn 2009-01-03 21:16:48

Смежные вопросы