Оптимальная архитектура данных для тегов, облаков и поиска (например, StackOverflow)?
Мне бы очень хотелось знать, как тегирование и поиск стека переполнены, потому что он работает очень хорошо.
Что такое хорошая модель базы данных/поиска, если я хочу сделать все следующее:
- Сохранение тегов на разных объектах (как нормализованные таблицы, сущности, теги и Entity_Tag?)
- Поиск элементов с определенными тегами
- Создание облака тегов всех тегов, которые применяются к определенному набору результатов
- Как показать список тегов для каждого элемента в результатах поиска?
Возможно, имеет смысл хранить теги в нормализованной форме, но также как строку с разделителями пробелов для целей # 2, # 4 и, возможно, # 3. Мысли?
Я слышал, что он сказал, что Qaru использует Lucene для поиска. Это правда? Я слышал пару подкастов, обсуждавших оптимизацию SQL, но ничего о Lucene. Если они используют Lucene, мне интересно, сколько из результатов поиска происходит от Lucene и есть ли облачное облако тегов "Lucent" из Lucene.
Ответы
Ответ 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.
-
Этот подход упрощает поиск элементов через Tag, присоединяется к EntityTag, называет его днем.
-
Вам нужна дополнительная операция для выбора отдельных тегов для набора результатов. Итак, a.) Вытащите результирующий набор, б.) Нормализуйте пространство тегов. Я думаю, что вы делаете это независимо от того, что ответ на # 1 - даже набивка тегов в одно поле будет по-прежнему давать повторяющиеся теги (и вы должны десериализовать их для выполнения этой операции - так что больше работы, еще один аргумент для полностью реляционного подход).
-
Все еще легко. Здесь одна область, где сериализованный подход работает лучше. Не нужно присоединяться к дочерним тегам, это прямо в Entity. Тем не менее, вытаскивание тэгов 0..n через объединение двух таблиц не кажется мне слишком сложным. Если вы говорите о первоочередных соображениях, сначала создайте его, а затем оптимизируйте с помощью кеша или денорма.
Другой вариант - "сделать оба". Это похоже на преждевременную оптимизацию, но вы можете сделать полный нормализованный подход для поддержки любых операций, ориентированных на тег, и сериализации, чтобы продолжать иметь денормализованную версию прямо в Entity. Немного больше работы, некоторый потенциал, чтобы выпасть из синхронизации, если не полностью охвачены, но лучше всего из двух миров, если есть реальные ограничения на полностью нормализованный способ в ваших случаях использования.
Lucene также интересна, вы можете объявить конкретные метаданные в индексах IIRC, поэтому вы также можете использовать поиск тегов таким же образом. Мое подозрение в том, что если вы заходите слишком далеко по этому пути, то в конечном итоге у вас будут некоторые отключения между тем, что вы храните в базе данных и индексом в какой-то момент. Я могу положительно говорить о Lucene, он очень прост в использовании и удобен в использовании. Я считаю, что .Text использовал его для поиска, и он поддерживал весь weblogs.asp.net до перехода на сервер сообщества. Я придерживаюсь этого для полнотекстового поиска, если MSSQL не находится в изображении/достаточен, решите проблемы с тегами в базе данных imo.