Решение для пары «имя-значение» можно выполнить в базе данных.
В этом примере 4 таблицы, персона, требование, домашнее животное, домашний питомец
Персона и Питомец имеют идентификатор и имя.
У каждого человека также есть одно или несколько требований. Требования имеют имя, сравнение и значение.
У каждого питомца есть один или несколько PetStats, которые состоят из имени и значения
с этой настройкой, можно найти короткошерстных собак с запросом вроде:
select * from pet, petstat
where pet.id = petstat.petId
and petstat.name = 'hair'
and petstat.value = 'short'
and petId in (select petId from petstat
where name='type' and value = 'dog')
Следующий запрос будет сопоставлять людей с домашними животными, когда домашним животным удовлетворяются все требования человека.
select person.name, pet.name from person, pet
where (select count(*) from requirement where requirement.personid = person.id)
= (select count(*) from requirement, petstat
where requirement.comparison = 'eq'
and requirement.name = petstat.name
and requirement.value = petstat.value
and requirement.personId = person.id
and petstat.petid = pet.id)
+ (select count(*) from requirement, petstat
where requirement.comparison = 'lt'
and requirement.name = petstat.name
and requirement.value > petstat.value
and requirement.personId = person.id
and petstat.petid = pet.id)
+ (select count(*) from requirement, petstat
where requirement.comparison = 'gt'
and requirement.name = petstat.name
and requirement.value < petstat.value
and requirement.personId = person.id
and petstat.petid = pet.id);
Сравнения «меньше» и «больше, чем» можно было бы лучше обрабатывать, добавляя числовые поля в таблицы требований и таблицы исходных данных и добавляя в запрос больше элементов, но это дает хорошую статистику.
Вот вставки для создания тестовых данных.
delete from person;
insert into person (id, name) values (1, 'Joe');
insert into person (id, name) values (2, 'Bill');
insert into person (id, name) values (3, 'Erik');
insert into person (id, name) values (4, 'Mike');
delete from pet;
insert into pet (id, name) values (1, 'spot');
insert into pet (id, name) values (2, 'mittens');
insert into pet (id, name) values (3, 'rover');
delete from requirement;
insert into requirement (personid, name, comparison, value) values (1, 'type', 'eq', 'dog');
insert into requirement (personid, name, comparison, value) values (1, 'color', 'eq', 'black');
insert into requirement (personid, name, comparison, value) values (2, 'type', 'eq', 'fish');
insert into requirement (personid, name, comparison, value) values (3, 'type', 'eq', 'dog');
insert into requirement (personid, name, comparison, value) values (3, 'hair', 'eq', 'long');
insert into requirement (personid, name, comparison, value) values (4, 'type', 'eq', 'dog');
insert into requirement (personid, name, comparison, value) values (4, 'weight', 'lt', '30');
insert into requirement (personid, name, comparison, value) values (4, 'weight', 'gt', '20');
delete from petstat;
insert into petstat (petId, name, value) values (1, 'type', 'dog');
insert into petstat (petId, name, value) values (1, 'color', 'black');
insert into petstat (petId, name, value) values (1, 'hair', 'short');
insert into petstat (petId, name, value) values (2, 'type', 'cat');
insert into petstat (petId, name, value) values (3, 'type', 'dog');
insert into petstat (petId, name, value) values (3, 'weight', '25');
insert into petstat (petId, name, value) values (3, 'color', 'brown');