De entity-attribute-value model dat u voorstelt, zou in dit scenario kunnen passen.
Wat betreft de filterquery, je moet begrijpen dat je met het EAV-model veel zoekkracht opoffert, dus dit kan behoorlijk lastig worden. Maar dit is een manier om uw probleem aan te pakken:
SELECT stuff.id
FROM stuff
JOIN (SELECT COUNT(*) matches
FROM table
WHERE (`key` = X1 AND `value` = V1) OR
(`key` = X2 AND `value` = V2)
GROUP BY id
) sub_t ON (sub_t.matches = 2 AND sub_t.id = stuff.id)
GROUP BY stuff.id;
Een onelegant kenmerk van deze benadering is dat u het aantal attribuut/waarde-paren moet specificeren dat u verwacht te matchen in sub_t.matches = 2
. Als we drie voorwaarden hadden, hadden we sub_t.matches = 3
. moeten specificeren , enzovoort.
Laten we een testcase bouwen:
CREATE TABLE stuff (`id` varchar(20), `key` varchar(20), `value` varchar(20));
INSERT INTO stuff VALUES ('apple', 'color', 'red');
INSERT INTO stuff VALUES ('mango', 'color', 'yellow');
INSERT INTO stuff VALUES ('banana', 'color', 'yellow');
INSERT INTO stuff VALUES ('apple', 'taste', 'sweet');
INSERT INTO stuff VALUES ('mango', 'taste', 'sweet');
INSERT INTO stuff VALUES ('banana', 'taste', 'bitter-sweet');
INSERT INTO stuff VALUES ('apple', 'origin', 'US');
INSERT INTO stuff VALUES ('mango', 'origin', 'MEXICO');
INSERT INTO stuff VALUES ('banana', 'origin', 'US');
Vraag:
SELECT stuff.id
FROM stuff
JOIN (SELECT COUNT(*) matches, id
FROM stuff
WHERE (`key` = 'color' AND `value` = 'yellow') OR
(`key` = 'taste' AND `value` = 'sweet')
GROUP BY id
) sub_t ON (sub_t.matches = 2 AND sub_t.id = stuff.id)
GROUP BY stuff.id;
Resultaat:
+-------+
| id |
+-------+
| mango |
+-------+
1 row in set (0.02 sec)
Laten we nu nog een vrucht invoegen met color=yellow
en taste=sweet
:
INSERT INTO stuff VALUES ('pear', 'color', 'yellow');
INSERT INTO stuff VALUES ('pear', 'taste', 'sweet');
INSERT INTO stuff VALUES ('pear', 'origin', 'somewhere');
Dezelfde zoekopdracht zou terugkeren:
+-------+
| id |
+-------+
| mango |
| pear |
+-------+
2 rows in set (0.00 sec)
Als we dit resultaat willen beperken tot entiteiten met origin=MEXICO
, zouden we nog een OR
. moeten toevoegen staat en controleer op sub_t.matches = 3
in plaats van 2
.
SELECT stuff.id
FROM stuff
JOIN (SELECT COUNT(*) matches, id
FROM stuff
WHERE (`key` = 'color' AND `value` = 'yellow') OR
(`key` = 'taste' AND `value` = 'sweet') OR
(`key` = 'origin' AND `value` = 'MEXICO')
GROUP BY id
) sub_t ON (sub_t.matches = 3 AND sub_t.id = stuff.id)
GROUP BY stuff.id;
Resultaat:
+-------+
| id |
+-------+
| mango |
+-------+
1 row in set (0.00 sec)
Zoals bij elke benadering zijn er bepaalde voor- en nadelen bij het gebruik van het EAV-model. Zorg ervoor dat u het onderwerp uitgebreid onderzoekt in de context van uw aanvraag. U kunt zelfs een alternatieve relationele database overwegen, zoals Cassandra , CouchDB , MongoDB , Voldemort , HBase , SimpleDB of andere sleutelwaardewinkels.