La entity-attribute-value modèle que vous suggérez pourrait s'adapter à ce scénario.
En ce qui concerne la requête de filtrage, vous devez comprendre qu'avec le modèle EAV, vous sacrifierez beaucoup de puissance de requête, cela peut donc devenir assez délicat. Cependant, voici une façon de résoudre votre problème :
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;
Une caractéristique peu élégante de cette approche est que vous devez spécifier le nombre de paires attribut/valeur que vous vous attendez à faire correspondre dans sub_t.matches = 2
. Si nous avions eu trois conditions, nous aurions dû spécifier sub_t.matches = 3
, et ainsi de suite.
Créons un scénario de test :
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');
Requête :
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;
Résultat :
+-------+
| id |
+-------+
| mango |
+-------+
1 row in set (0.02 sec)
Insérons maintenant un autre fruit avec color=yellow
et taste=sweet
:
INSERT INTO stuff VALUES ('pear', 'color', 'yellow');
INSERT INTO stuff VALUES ('pear', 'taste', 'sweet');
INSERT INTO stuff VALUES ('pear', 'origin', 'somewhere');
La même requête renverrait :
+-------+
| id |
+-------+
| mango |
| pear |
+-------+
2 rows in set (0.00 sec)
Si nous voulons restreindre ce résultat aux entités avec origin=MEXICO
, il faudrait ajouter un autre OR
condition et vérifiez sub_t.matches = 3
au lieu de 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;
Résultat :
+-------+
| id |
+-------+
| mango |
+-------+
1 row in set (0.00 sec)
Comme dans toute approche, l'utilisation du modèle EAV présente certains avantages et inconvénients. Assurez-vous de faire des recherches approfondies sur le sujet dans le contexte de votre candidature. Vous pouvez même envisager des bases de données relationnelles alternatives, telles que Cassandra , CouchDB , MongoDB , Voldemort , HBase , SimpleDB ou d'autres magasins de valeurs-clés.