質問

I have a Product Database, and I want to attach text, images, videos to the products. I also want that each entity (text, images or videos) have a tag, for further organisation on application.

I thought of using this model:

Content:

content_id|content_product_id|content_type|content_tag_id|content_url|content_title|content_text

Tag

tag_id|tag_name

This mean to use Entity(content_product_id) - Attribute(content_tag_id) - Value (content_url or content_title|content_text) Model.

After reading a lot, I understood that is a bad idea to use this modeling pattern (described as a database antipattern, unscalable and causing performance issues), have you an idea for an alternative method for this ?

I want to use Doctrine ORM, and I would like to find an method that will be easily compatible with that data mapper

役に立ちましたか?

解決

I'd create a general table for any type of content:

CREATE TABLE ProductContents(
  content_id INT AUTO_INCREMENT PRIMARY KEY,
  content_type INT NOT NULL
  -- other general attributes like when it was created, by whom, etc.
);

For each text, image, or video, insert one row into this table. If you use an auto-increment primary key, this table is responsible for generating the id number.

For tags, now you simply have a many-to-many relationship between ProductContent and Tags. This is represented by an intersection table.

CREATE TABLE Tags (
  tag_id INT AUTO_INCREMENT PRIMARY KEY,
  tag TEXT NOT NULL
);

CREATE TABLE ProductContentTagged (
  content_id INT, 
  tag_id INT, 
  PRIMARY KEY (content_id, tag_id),
  FOREIGN KEY (content_id) REFERENCES ProductContents(content_id),
  FOREIGN KEY (tag_id) REFERENCES Tags(tag_id),
);

Then if you have any attributes specific to each type of content, create auxiliary tables for each type, with a one-to-one relationship to the content table.

CREATE TABLE ProductContentTexts (
  content_id INT PRIMARY KEY,
  content TEXT NOT NULL,
  FOREIGN KEY (content_id) REFERENCES ProductContents(content_id)
);

CREATE TABLE ProductContentImages (
  content_id INT PRIMARY KEY,
  image_path TEXT NOT NULL,
  FOREIGN KEY (content_id) REFERENCES ProductContents(content_id)
);

CREATE TABLE ProductContentVideos (
  content_id INT PRIMARY KEY,
  video_path TEXT NOT NULL,
  FOREIGN KEY (content_id) REFERENCES ProductContents(content_id)
);

Note these auxiliary tables don't have an auto-increment column. They don't need to -- they will always use the value that was generated by the ProductContents table, and you're responsible for inserting that value.

他のヒント

Bill Karwin's answer is very good.

However, since you say:

I want to use Doctrine ORM, and I would like to find an method that will be easily compatible with that data mapper

I'll relate his answer to that particular ORM.

What Bill describes is inheritance. You have a superclass of "content", represented by a table that holds all the shared data. Then you have subclasses (text, image, video) that extend that superclass by adding content-type-specific columns.

Doctrine2 will do essentially what Bill has suggested when you use class-table inheritance. Once you configure your entities properly, it will create a set of tables very similar to what Bill describes.

So, with Doctrine you cave the Content entity, which is extended by Image, Text, and Video.

As far as the tagging goes, you would just create a basic Tag entity, and Content would have a ManyToMany relationship to Tag. Doctrine will handle creating the intermediate table for you.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top