What I have done in the past is to use something like this:
1) Each document has a logical type associated with it.
2) Set up tables for metadata for each logical type. Each row can store all metadata associated with the document.
The other approach is that of key-value-modelling which can actually be ok or not depending on what you are doing with it. In this case you have a metadata table which stores all metadata, one value per record, for all documents. This works best if you find a reasonable way to aggregate the data in result sets, and if you aren't doing complex searches across multiple metadata fields.
I might suggest to reorganize schema, to make it more scalable.
DROP
columns entityId
and entityType
.
CREATE
an Objects
(or Entities
) table which will store public / shared information for all objects / entities. It's primary key will migrate to Companies
and to Houses
with 1:1
relation. For one object might exist only one company OR only one house. Also, you will have to remove AUTO_INCREMENT
from Companies
and Houses
, because in this case they will no longer generate identifiers themselves.
- Add foreign key to
Contacts
table from shared Objects
table - contacts might exist for any type of object.
Structure might look like this:
You might obtain entity type by following query:
SELECT
cnt.*,
CASE
WHEN NOT cmp.id IS NULL THEN 1
WHEN NOT hs.id IS NULL THEN 2
END as entityType
FROM
Contacts as cnt
INNER JOIN Objects as obj ON cnt.objectId = obj.id
LEFT JOIN Companies as cmp ON cmp.id = obj.id
LEFT JOIN Houses as hs ON cmp.id = hs.id
Also, note that entityId
becomes objectId
in this case.
Here is a CREATE
-script for benchmarking and test:
CREATE TABLE IF NOT EXISTS `Objects` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`shared_property1` VARCHAR(45) NULL,
`shared_property2` VARCHAR(45) NULL,
`etc` VARCHAR(45) NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `Companies` (
`id` BIGINT NOT NULL,
`company_name` VARCHAR(300) NULL,
`private_property1` VARCHAR(45) NULL,
`private_property2` VARCHAR(45) NULL,
`etc` VARCHAR(45) NULL,
PRIMARY KEY (`id`),
CONSTRAINT `FK_Companies_Objects`
FOREIGN KEY (`id`)
REFERENCES `Objects` (`id`)
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `Houses` (
`id` BIGINT NOT NULL,
`address` VARCHAR(300) NULL,
`private_property1` VARCHAR(45) NULL,
`private_property2` VARCHAR(45) NULL,
`etc` VARCHAR(45) NULL,
PRIMARY KEY (`id`),
CONSTRAINT `FK_Houses_Objects`
FOREIGN KEY (`id`)
REFERENCES `Objects` (`id`)
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `Contacts` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`objectId` BIGINT NOT NULL,
`name` VARCHAR(300) NULL,
`phone` VARCHAR(300) NULL,
`email` VARCHAR(300) NULL,
PRIMARY KEY (`id`),
INDEX `FK_Contacts_Objects` (`objectId` ASC),
CONSTRAINT `FK_Contacts_Objects`
FOREIGN KEY (`objectId`)
REFERENCES `Objects` (`id`)
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB;
Best Answer
For those purpose, I only use relations in the USER table with users ids stored as pointers inside.
Using a cloud code function, I provide a parameter to add , del or whatever instructions to apply to a single or an array of users. Cloud gives the opportunity to create collateral events such as "a user like this"
As a reading step, a query is applied to the relation to retrieve parts or all users.
The column is named with the purpose such as I will add 2 columns to mention respectively "like" , "dontLike"
However, if one need more than a single information , a second table needs to be created and linked also with a relation. For example, a new table with a first column which is a regular pointer to users, other columns to stored the additional attributes. Which means that this new table must be first saved, to be able to stored its id in the relation.