Существует ли согласованная идеальная схема для маркировки

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

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

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

Фото

  • PhotoID
  • PhotoAlbumID
  • Название
  • Дата

Фотоальбом

  • ALBUMID
  • ALBUMNAME
  • AlbumDate

Ответы

Ответ 1

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

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

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

Ответ 2

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

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

photos
  photoid
  caption
  filename
  date

tags
  tagid
  tagname

phototags
  photoid
  tagid

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

Еще одна проблема, с которой вам придется столкнуться, - проблема нормализации тега. Это не имеет ничего общего с нормализацией базы данных - просто убедитесь, что (например) теги "StackOverflow", "stackoverflow" и "stack overflow" совпадают. Множество мест запрещают пробельные символы или автоматически лишают его. Иногда вы увидите одно и то же для пунктуации, что делает "StackOverflow" таким же, как "Stack-Overflow". Auto-lowercasing довольно стандартный. Вы даже увидите нормальную нормализацию случая - например, сделать "С#" таким же, как "csharp".

Счастливые тегирования!

Ответ 3

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

Метки

  • TagID
  • TagName
  • TagDescription

PhotoTags

  • PhotoID
  • TagID

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

Ответ 4

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

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

Ответ 5

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

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

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

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

Ответ 6

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

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

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

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

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

Когда кто-то выполняет поиск с использованием тега, я просматриваю значение на карте, получаю список идентификаторов, а затем извлекаю эти ошибки с помощью SQL с "где id в (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;

    }

Ответ 7

Быстрая заметка о том, как обрабатывать теги:

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

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

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