2009-08-04 9 views
0

Je dois être en mesure de faire correspondre les propriétaires potentiels aux animaux abandonnés en fonction de divers critères et emplacements.Comment modéliser les différents critères?

Le propriétaire aura un ensemble de critères particulier. Type d'animal = "chien", race = "Labrador Retriever", l'âge devra être compris entre 1 et 5, sexe = mâle, et ainsi de suite ...

L'animal aura également un ensemble de critères particuliers. Le type d'animal = "Chien", âge = 3, sexe = mâle, race = "Chihuahua".

L'animal pourrait également être: type = "chat", âge = "12", sexe = femelle, race = "tigre". J'ai également un modèle "Location" pour le propriétaire et l'animal (polymorphe) qui contient les informations relatives à l'emplacement de l'animal ou du propriétaire.

Donc cette partie est facile ...

La partie dure (au moins pour moi) est quand je dois préciser des critères différents pour les différents types d'animaux. Donc un animal de type = "chien" peut avoir un critère de "peut aller chercher?" alors qu'un animal de type chat peut avoir un critère de "dégrafé"? et un animal de type "poisson" peut avoir des critères de "motif" avec plusieurs options de ["tacheté", "rayé", "uni"]. Ce que j'ai maintenant est un modèle "animal" avec l'information générique sur les animaux (âge, sexe, race), puis j'ai un modèle de races avec les différentes races par type d'animal, mais je n'arrive pas à comprendre comment extraire les critères qui diffèrent entre les types d'animaux.

Encore une fois, c'est juste une analogie parce que je ne pense pas que mon problème réel aura un sens à quelqu'un d'autre. Ce dont j'ai besoin, c'est de quelques indications dans la bonne direction, peut-être un lien ou deux. Je n'arrive pas à trouver comment faire cela dans Rails sans créer une table séparée pour chaque ensemble de critères, comme dans dog_criteria, cat_criteria, fish_criteria, et ainsi de suite ...

Répondre

0

Dans le monde de la modélisation de logiciels, cela serait évidemment fait avec un classe pour chaque espèce, IE "Chien", "Chat", "Poisson" qui prolongent "Animal". Dans le monde des bases de données relationnelles, cela devient un peu plus difficile à représenter. Si vous vouliez faire correspondre cette approche orientée objet à votre base de données, vous auriez une table pour "Animaux", puis une table pour chaque espèce, "Chat", "Chien" et "Poisson". Alors vous auriez probablement une table d'espèces (ou une énumération codée en dur dans votre code) qui vous donnerait une valeur à placer dans la rangée d'animaux pour quelle espèce chaque animal était. Cela vous dirait comment rechercher des informations supplémentaires pour chaque animal.

Ce n'est probablement pas la meilleure approche. Ce que vous avez est plus ce que j'appellerais "données personnalisées" pour chaque animal. Vous devez définir une table avec une liste d'attributs personnalisés et une autre table pour faire correspondre ces attributs à une valeur pour chaque ligne d'animaux.

Si vous souhaitez rendre plus pratique la visualisation et le contrôle des attributs pouvant s'appliquer à quelles espèces, vous pouvez créer un troisième tableau pour les "Catégories" qui serait lié à l'espèce animale et à une collection d'attributs. Ensuite, vous devez spécifier l'ID de catégorie sur la rangée d'animaux.

tables Exemples:

Animals 
------- 
ID 
Age 
Sex 
Species 
Breed 

Parameters 
---------- 
ID 
Name 

Parameter Values 
---------------- 
ParameterID 
AnimalID 
Value 

Categories (optional - add CategoryID to animals) 
--------------------- 
ID 
Name 

Category Parameters 
------------------- 
CategoryID 
ParameterID 
+0

Cela semble être un moyen raisonnable d'y remédier. J'espère ne pas rencontrer de problèmes majeurs! Une question, comment pourrais-je stocker plusieurs attributs d'un paramètre particulier? Comme un hachage dans la table de paramètres? – Shane

+0

Par attributs voulez-vous dire la valeur? Comme le paramètre "Couleur", les attributs "Rouge", "Vert" et "Bleu"? Si c'est le cas, alors je choisirais l'une des deux options: 1) Stockez les valeurs dans une table séparée, avec un ID, ParameterID, "Value", et "Label", puis stockez le "ID" de la valeur appropriée dans le tableau Valeurs de paramètres. 2) Stockez simplement la valeur directement dans la table Parameter Values, et ayez une classe Enum dans votre code pour contrôler la recherche des valeurs appropriées. L'option 2 est plus facile (pas de nouvelles tables). – Nicole

1

Parfois, nous avons recours à un nom simple/paires de valeurs (ou triples nom/valeur/type) pour ces propriétés. Cela évite d'ajouter de nouveaux types (et des tables de base de données) pour chaque espèce animale dans le monde. Ou pire pour chaque race: Considérez caniches ... ils pourraient avoir un champ supplémentaire "rasé décorativement" ... et St Bernards, capacité brandy ...

+0

J'ai vraiment considéré cette voie, mais elle n'a pas "senti" juste (faute d'un meilleur mot). N'aurais-je pas fondamentalement perdu la possibilité de modifier les attributs disponibles pour un paramètre particulier? Je ne serais pas capable de trouver tous les caniches qui sont "rasés de façon décorative" le ferais-je? – Shane

+0

Nous passons de la typage fort (compiler le contrôle du temps) à la faille (attributs arbitraires). Vous pouvez avoir une sorte de "schéma" pour les attributs, donc au moment de l'exécution, vous pouvez déterminer que les caniches peuvent être rasés. C'est plus de code, et le compilateur n'aide pas à vérifier que vous essayez de ne raser que des caniches, mais il simplifie la persistance. – djna

0

La solution de valeur du nom de paire peut être fait dans la base de données.

Dans cet exemple il y a 4 tables, personne, exigence, animal familier, petstat

personne et animaux ont chacun un identifiant et un nom.
Chaque personne a également une ou plusieurs exigences. Les exigences ont un nom, une comparaison et une valeur.
Chaque animal a un ou plusieurs PetStats qui se composent d'un nom et une valeur

avec cette configuration, les chiens à poils courts pourraient être trouvés avec une requête comme:

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') 

La requête suivante correspondront personnes aux animaux de compagnie lorsque toutes les exigences de la personne sont satisfaites par un animal de compagnie.

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); 

Le moins et plus que les comparaisons pourraient être mieux gérées en ajoutant des champs numériques à l'exigence et petstat tables et en ajoutant plus de pièces à la requête, mais cela donne une bonne stat.

Voici les inserts pour créer les données de test.

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'); 
Questions connexes