Оптимальная архитектура данных для тегов, облаков и поиска (например, StackOverflow)? - PullRequest
38 голосов
/ 24 октября 2008

Хотелось бы узнать, как устроены теги и поиск в Stack Overflow, потому что, кажется, это работает довольно хорошо.

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

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

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

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

Ответы [ 2 ]

57 голосов
/ 28 октября 2008

Ничего себе, я только что написал большое сообщение, и ТАК задохнулся и повесил его, и когда я нажал кнопку «Назад», чтобы повторить, редактор разметки был пуст. Aaargh.

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

Что касается переполнения стека, то получается, что они используют полнотекстовый поиск SQL Server 2005 .

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

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

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

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

  1. В БД 3 таблицы: Entity, Tag, Entity_Tag. Я использую БД для:
    • Создание облаков тегов для всего сайта
    • просмотр по тегу (то есть URL-адреса, подобные SO * / questions / tagged / ASP.NET )
  2. Для поиска я использую Lucene + NHibernate.Search
    • Теги объединяются в TagString, которая индексируется Lucene
      • Итак, у меня есть все возможности механизма запросов Lucene (запросы И / ИЛИ / НЕ)
      • Я могу искать текст и фильтр по тегам одновременно
      • Анализатор Lucene объединяет слова для лучшего поиска по тегам (т. Е. При поиске по тегу "test" также можно найти материал с тегом "testing")
    • Lucene возвращает потенциально огромный набор результатов, который я разбил на 20 результатов
    • Затем NHibernate загружает полученные сущности по Id, либо из БД, либо из кеша сущностей
    • Так что вполне возможно, что поиск приведет к 0 попаданиям в БД
  3. Пока не делаю этого, но я думаю, что я, вероятно, попытаюсь найти способ построить облако тегов из TagString в Lucene, а не делать еще один удар по БД
  4. Еще не сделал этого, но я, вероятно, сохраню TagString в БД, чтобы я мог показать список тегов сущности без необходимости делать еще 2 соединения.

Это означает, что когда бы ни изменялись теги сущности, я должен:

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

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

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

5 голосов
/ 25 октября 2008

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

Мои лучшие догадки без долгих размышлений :) 1003 *

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

Так что мой первоначальный дубль - это, вероятно, Entity -> EntityTag <- Tag. </p>

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

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

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

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

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

...