Каков наиболее эффективный способ хранения тегов в базе данных?

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

Моя идея такая:

Table: Items
Columns: Item_ID, Title, Content

Table: Tags
Columns: Title, Item_ID

Это слишком медленно? Есть ли способ лучше?


person Logan Serman    schedule 02.12.2008    source источник
comment
Ранее спрашивалось: stackoverflow .com / questions / 20856 /.   -  person DrBloodmoney    schedule 02.12.2008
comment
С 2016 года используйте Solr или Elasticsearch.   -  person Charles L.    schedule 09.09.2016


Ответы (8)


У одного предмета будет много тегов. И одна метка будет принадлежать многим предметам. Это означает, что вам, возможно, понадобится промежуточная таблица, чтобы преодолеть препятствие «многие ко многим».

Что-то типа:

Таблица: элементы
Столбцы: Item_ID, Item_Title, Content

Таблица: Теги
Столбцы: Tag_ID, Tag_Title

Таблица: Items_Tags
Столбцы: Item_ID, Tag_ID

Может случиться так, что ваше веб-приложение очень популярно и в будущем потребует дестабилизации, но слишком рано мутить воду бессмысленно.

person Simon Scarfe    schedule 02.12.2008
comment
По теме: stackoverflow.com/questions/20856/ - person Cherian; 04.10.2009
comment
если есть что-то вроде tagGroup, как с этим обращаться, например, теги сгруппированы по категориям, например: Языки программирования: c #, vb, pearl. ОС: windows7, dos, linux и т. Д. - person Thunder; 11.02.2011
comment
@Thunder: предполагая, что один тег может принадлежать только к одной категории, я бы создал таблицу TagCategory, состоящую из category_id и category_name. Оттуда я бы добавил поле category_id в таблицу Tags и выполнил соединение с ним. - person Simon Scarfe; 13.02.2011

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

Таким образом, в таблице тегов просто есть tagid, itemid, tagname.

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

Для отображения списка тегов вы просто используете DISTINCT или GROUP BY, и, конечно же, вы можете легко подсчитать, сколько раз тег используется.

person Neil Barnwell    schedule 03.12.2008

Если вы не против использования нестандартных вещей, Postgres версии 9.4 и выше имеет возможность хранить запись типа текстового массива JSON.

Ваша схема будет:

Table: Items
Columns: Item_ID:int, Title:text, Content:text

Table: Tags
Columns: Item_ID:int, Tag_Title:text[]

Для получения дополнительной информации см. Этот отличный пост Джоша Беркуса: http://www.databasesoup.com/2015/01/tag-all-things.html.

Существует больше различных вариантов, тщательно сравниваемых по производительности, и тот, который предложен выше, в целом является лучшим.

person Dmitry Shvedov    schedule 17.08.2015

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

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

person Rockcoder    schedule 02.12.2008

Я бы предложил использовать третью промежуточную таблицу для хранения ассоциаций тегов ‹=> элементов, поскольку у нас есть отношения «многие ко многим» между тегами и элементами, т.е. один элемент может быть связан с несколькими тегами, а один тег может быть связан с несколькими элементами. HTH, клапан.

person Valentin V    schedule 02.12.2008

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

person Adam Pope    schedule 02.12.2008

Элементы должны иметь поле «ID», а теги должны иметь поле «ID» (первичный ключ, кластеризованный).

Затем создайте промежуточную таблицу ItemID / TagID и поместите туда "Perfect Index" .

person Timothy Khouri    schedule 02.12.2008

Схема тегов: Таблицы тегов и атрибуты:

Таблицы:

tags (each row only keeps information about a particular tag)
taggings (each row keeps information about trigger and who will receive the trigger )
products_tags (each row keeps information about tag with particular product)
tag_status (each row keeps track of a tag status)

Таблица: теги Атрибуты таблицы тегов:

id(PK)
userId(FK users)(not null)(A tag only belongs to one user, but  a user can create multiple tags. So it is one to many relationships.)
genreId(FK products_geners)(not null)
name (string) (not null)
description (string)
status (int) (0=inactive, 1=pending, 2=active, there could be more flag)
rank(int)  (rank is the popularity of a particular tag), this field can be use for sorting among similar tags.)
type (int) (0=type1, 1=type2, 2=type3)
photo(string)
visibility (int) (0=public, 2=protected, 3 = private)(private means the tag only  visible to assigned users of a product, protected means a tag only visible to all friends and followers of the creator of the tag, public means search by public, such as all admin created tag)
createdAt(timestamp for the tag was created at)
updatedAt (timestamp for the tag last time updated)
deletedAt (default value null) (timestamp when tag was deleted, we need this field because we will delete tag permanently from audit table). 

Примечание: сохранение поля № 10 пригодится позже.

Таблица: теги:

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

Атрибуты таблицы тегов:

Id(PK)
tagId(a tagging row only belongs to a tag, but a tag can have multiple row).
taggableId (id of a user who will receive notification)
taggableType(int) (0=notification, 1=feed message)
taggerId(the person who triggered the broadcast)
taggerType(ad, product, news)
createdAt(timestamp for the tag was created at)

Таблица: products_tags

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

Атрибуты таблицы атрибутов тегов:

Id (PK)
productId(FK)
tagId(FK)

Таблица: tag_status

Когда пользователь создаст тег, в этой таблице будет создана строка с tagId и статусом по умолчанию inactive / pending, администратор извлечет все теги из таблицы тегов, где status = pending / inactive, после просмотра тега, если администратор одобрил тег, затем значение статуса в таблице тегов будет одобрен, а строка tag_status будет удалена. Если администратор отклонен, значение поля статуса таблицы tag_status будет отклонено, и будет транслироваться триггер, а получатель отправит уведомление связанному пользователю этого тега с сообщением о том, что его тег отклонен.

id(PK)
senderId(Id of the user)
receiverId(Id of admin user)
createdAt(timestamp of created at)
updatedAt(timestamp of updated at)
deletedAt(timestamp of deletedAt) default value null
expiredAt (if a tag never gets approved it will expire after a certain time for removing its information from the database. If a rejected tag gets updated by user then expiredAt will reset to new future time)
status 
Message (string varchar(256)) (message for user)
person Lord    schedule 13.05.2021