Существует ли согласованная идеальная схема для пометки - PullRequest
19 голосов
/ 06 октября 2008

У меня есть веб-сайт с фотографиями, и я хочу поддерживать теги, так как моя первоначальная категория начинает сбой (некоторые фотографии - это семья и каникулы, или школа и друзья). Существует ли согласованная схема тегирования БД?

Я все еще хочу поддерживать добавление фотографий в альбом.

Сейчас у меня есть несколько таблиц:

Фотографии

  • PhotoID
  • PhotoAlbumID
  • Подпись
  • Дата

Фотоальбом

  • ALBUMID
  • ALBUMNAME
  • AlbumDate

Ответы [ 7 ]

23 голосов
/ 06 октября 2008

Существуют различные эффективные схемы, каждая из которых имеет свое собственное влияние на производительность для общих запросов, которые вам понадобятся по мере роста числа помеченных элементов:

Лично мне нравится иметь таблицу тегов и таблицу ссылок, которая связывает теги с элементами, поскольку она денормализована (без дублирования имен тегов), и я могу хранить дополнительную информацию в таблице ссылок (например, когда элемент был помечен) когда необходимо.

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

11 голосов
/ 06 октября 2008

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

Поскольку это отношение «многие-многие» (каждый тег может принадлежать любому количеству фотографий - каждая фотография может иметь много тегов), теория реляционных баз данных предусматривает создание таблицы фотографий, таблицы тегов и таблицы перекрестных ссылок для ссылки. им.

photos
  photoid
  caption
  filename
  date

tags
  tagid
  tagname

phototags
  photoid
  tagid

Это приводит к проблемам с масштабированием при выборе из действительно больших наборов данных, но так же поступают и все менее нормализованные схемы (например, сортировка и фильтрация по текстовому полю всегда будут медленнее, чем при использовании целого числа). Если вы вырастите настолько большим, насколько вкусным, или, возможно, даже StackOverflow, вам, вероятно, придется сделать некоторое кэширование ваших наборов тегов.

Другая проблема, с которой вам придется столкнуться, - это проблема нормализации тегов. Это не имеет ничего общего с нормализацией базы данных - просто убедитесь, что (например) теги «StackOverflow», «stackoverflow» и «stack overflow» одинаковы. Многие места закрывают пробелы или автоматически удаляют их. Иногда вы можете увидеть то же самое для пунктуации - сделать «StackOverflow» таким же, как «Stack-Overflow». Авто-нижний регистр довольно стандартен. Вы даже увидите особый случай нормализации - например, сделав «c #» таким же, как «csharp».

Приятных пометок!

2 голосов
/ 06 октября 2008

Предлагаю посмотреть, как это делает установленное программное обеспечение с открытым исходным кодом. Например, Gallery хранит свои метаданные в базе данных, как вы, и довольно богат.

Я не думаю, что вы найдете "стандартную" схему, хотя. Ближайшая вещь, о которой я могу подумать, - это формат метаданных EXIF, который встроен в сами файлы изображений (с помощью камер и т. Д.).

2 голосов
/ 06 октября 2008

Как-то так мне приходит в голову: добавить эти две таблицы

Метки

  • TagID
  • TagName
  • TagDescription

PhotoTags

  • PhotoID
  • TagID

Вы также можете распространить это на альбомы, имея таблицу пересечения между Фотоальбомами и Тегами.

0 голосов
/ 06 октября 2008

Краткое примечание о том, как обращаться с тегами:

системы тегов могут варьироваться от очень жестко определенных тегов, где создание новых требует явной дополнительной работы (например, gmail), до очень свободных систем, где рекомендуется добавлять как можно больше тегов (например, flickr, или тегировать аудио-контент, где может быть транскрипция применяется непосредственно как теги).

В целом, легко индексируемый носитель (текст!) Должен иметь более жесткую систему, поскольку сам контент представляет собой теги - дополнительные теги существуют больше только для категоризации. Носитель, который труднее индексировать (изображения, видео), должен иметь гибкую систему, поддерживающую множество тегов, поскольку они являются вашей единственной надеждой при поиске.

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

0 голосов
/ 06 октября 2008

В моем приложении BugTracker.NET я предполагаю, что ошибок будет не слишком много. Может быть, десятки тысяч, но не десятки миллионов. Это предположение позволяет мне кэшировать теги и идентификаторы элементов, на которые они ссылаются.

В базе данных теги сохраняются по мере ввода вместе с ошибками в текстовом поле с разделителями-запятыми.

Когда поле тега добавляется или изменяется, это запускает фоновый поток, который выбирает все ошибки и их теги, анализирует текст, формируя карту, где ключ является тегом, а значение представляет собой список всех идентификаторов, которые есть этот тег. Затем я кеширую эту карту в объекте приложения Asp.Net.

Ниже приведен код, который я только что описал.

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

Когда кто-то выполняет поиск по тегу, я смотрю значение на карте, получаю список идентификаторов, а затем извлекаю эти ошибки, используя SQL с "where id in (1, 2, 3 ...)" пункт.

    public static void threadproc_tags(object obj)
    {
        System.Web.HttpApplicationState app = (System.Web.HttpApplicationState)obj;

        SortedDictionary<string,List<int>> tags = new SortedDictionary<string,List<int>>();

        // update the cache
        DbUtil dbutil = new DbUtil();
        DataSet ds = dbutil.get_dataset("select bg_id, bg_tags from bugs where isnull(bg_tags,'') <> ''");

        foreach (DataRow dr in ds.Tables[0].Rows)
        {
            string[] labels = btnet.Util.split_string_using_commas((string) dr[1]);

            // for each tag label, build a list of bugids that have that label
            for (int i = 0; i < labels.Length; i++)
            {

                string label = normalize_tag(labels[i]);

                if (label != "")
                {
                    if (!tags.ContainsKey(label))
                    {
                        tags[label] = new List<int>();
                    }

                    tags[label].Add((int)dr[0]);
                }
            }
        }

        app["tags"] = tags;

    }
0 голосов
/ 06 октября 2008

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

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

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

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

...