我正在考虑使用SQL软件来存储和查询具有松散架构的对象。
我们知道一个对象对应一个SQL表的一行,它的属性对应于列。通过“松散模式”,我的意思是一个对象可以具有不与表格(而非表格)结构硬连线的属性。可以将任意(属性,值)附加到对象。
让我举一个具体的例子说明:
对于给定的对象:
<subject>
name:data structures
tag:CS
description:easy
desired_seniority:5.0
<subject>
name:microprocessors
tag:CS,electronics <multi-valued
description:easy
desired_seniority:5.5 <numeric
和
<teacher>
name:John Doe
tag:electronics
seniority:5.8
查询将是
For each teacher,
return all subjects whose tags match and
whose desired seniority is less than or equal to the teacher's
教师'John Doe'将与主题'微处理器'匹配,因为他们共享标签'electronics'和他的资历< em> 5.8 大于受试者所需的资历 5.5
请注意,我在字符串中使用了数字(查询进行比较)和多值(查询在'匹配中)'字符串。
究竟是什么:我正在寻找合适的数据模型和相应的查询,让我可以模拟SQL软件上的松散架构。
我接受这些限制:
我看到了http://www.igvita.com/2010/03/01/schema-free-mysql-vs-nosql/和https://github.com/jamesgolick/friendly。
是的,有NoSQL数据库和特殊的ORM。我们使用Solr(太棒了!)。但是我会通过包含它们来避免增加项目的复杂性。模拟noSQL存储的性能开销不是问题。
答案 0 :(得分:2)
在MySql中我会使用这样的东西:
CREATE TABLE IF NOT EXISTS `subject` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`description` varchar(255) NOT NULL,
`desired_seniority` decimal(5,2) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
INSERT INTO `subject` (`id`, `name`, `description`, `desired_seniority`) VALUES
(1, 'data structures', 'easy', 5.00),
(2, 'microprocesors', 'easy', 5.50);
CREATE TABLE IF NOT EXISTS `subject_tag` (
`subject_id` int(10) unsigned NOT NULL,
`tag_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`subject_id`,`tag_id`),
KEY `fk_subject_tag_tags` (`tag_id`),
KEY `fk_subject_tag_subject` (`subject_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `subject_tag` (`subject_id`, `tag_id`) VALUES
(1, 1),
(2, 1),
(2, 2);
CREATE TABLE IF NOT EXISTS `tag` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
INSERT INTO `tag` (`id`, `name`) VALUES
(1, 'CS'),
(2, 'Electronics');
CREATE TABLE IF NOT EXISTS `teacher` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`surname` varchar(50) NOT NULL,
`seniority` decimal(5,2) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
INSERT INTO `teacher` (`id`, `name`, `surname`, `seniority`) VALUES
(1, 'John', 'Doe', 5.80),
(2, 'John', 'Brown', 5.30);
CREATE TABLE IF NOT EXISTS `teacher_tag` (
`teacher_id` int(10) unsigned NOT NULL,
`tag_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`teacher_id`,`tag_id`),
KEY `fk_teacher_tag_tag1` (`tag_id`),
KEY `fk_teacher_tag_teacher` (`teacher_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `teacher_tag` (`teacher_id`, `tag_id`) VALUES
(1, 2);
ALTER TABLE `subject_tag`
ADD CONSTRAINT `fk_subject_tag_tag` FOREIGN KEY (`tag_id`) REFERENCES `tag` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `fk_subject_tag_subject` FOREIGN KEY (`subject_id`) REFERENCES `subject` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE `teacher_tag`
ADD CONSTRAINT `fk_teacher_tag_tag` FOREIGN KEY (`tag_id`) REFERENCES `tag` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `fk_teacher_tag_teacher` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
为教师提供匹配的主题:
SELECT t.surname, t.name, GROUP_CONCAT( s.name SEPARATOR ' | ' ) AS subject_name
FROM teacher t
JOIN teacher_tag tt ON tt.teacher_id = t.id
JOIN subject_tag st ON st.tag_id = tt.tag_id
JOIN subject s ON st.subject_id = s.id
AND s.desired_seniority <= t.seniority
GROUP BY t.id