Подтвердить что ты не робот

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

Мне бы очень хотелось знать, как тегирование и поиск стека переполнены, потому что он работает очень хорошо.

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

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

Это означает, что всякий раз, когда теги Entity изменяются, я должен:

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

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

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

Ответ 2

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

Мои лучшие догадки без большого обсуждения:)

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

Итак, мой первоначальный взнос - это, вероятно, Entity → EntityTag < - Tag.

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

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

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

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

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