2009-06-14 13 views
0

BerkeleyDB est l'équivalent de la base de données d'une table de hachage Ruby ou d'un dictionnaire Python, sauf que vous pouvez stocker plusieurs valeurs pour une seule clé.Comment représenteriez-vous une entité relationnelle comme une seule unité de données récupérables dans BerkeleyDB?

Ma question est: Si vous vouliez stocker un type de données complexe dans une structure de stockage comme celle-ci, comment pourriez-vous y remédier?

Dans une table relationnelle normale, si vous souhaitez représenter une personne, vous créez une table avec des colonnes de types de données particulières:

Person 
-id:integer 
-name:string 
-age:integer 
-gender:string 

Quand il est écrit comme ça, vous pouvez voir comment une personne peut être comprise comme un ensemble de paires clé/valeur:

id=1 
name="john"; 
age=18; 
gender="male"; 

la personne en décomposition clé individuelle/paires de valeurs (name = « john ») est facile. Mais pour utiliser le format BerkeleyDB pour représenter une personne, il faudrait un moyen de recomposer la personne de ses paires clé/valeur constituantes. Pour cela, vous devrez imposer une structure d'encapsulation artificielle pour maintenir une personne ensemble en tant qu'unité.

Existe-t-il un moyen de le faire?

EDIT: Comme l'indique la réponse de Robert Harvey, il existe une fonctionnalité de persistance d'entité dans le Java edition de BerkeleyDB. Malheureusement, parce que je serai connecté à BerkeleyDB à partir d'une application Ruby en utilisant Moneta, j'utiliserai le standard edition qui, selon moi, me demande de créer une solution personnalisée en l'absence de ce support.

Répondre

3

Vous pouvez toujours sérialisation (appelé Ruby marshalling) les données sous forme de chaîne et de stocker qu'au lieu. La sérialisation peut être effectuée de plusieurs manières.

Avec YAML (avantage: lisible par l'homme, la mise en œuvre multiple dans différentes langues):

require 'yaml'; str = person.to_yaml 

Avec sérialisation (Ruby seule, même la version Ruby spécifique):

Marshal.dump(person) 

Cela ne fonctionnera si la classe de personne est une entité qui ne se réfère pas à d'autres objets que vous ne voulez pas inclure. Par exemple, les références à d'autres personnes devraient être traitées différemment.

2

Si votre datastore est en mesure de le faire (et BerkeleyDB fait AFAICT) Je venais de stocker une représentation des attributs d'objet claveté avec l'objet Id, sans diviser les attributs d'objet dans différentes clés.

E.g. donné:

Person 
-id:1 
-name:"john" 
-age:18 
-gender:"male" 

je aimerais stocker la représentation YAML dans BerkleyDB avec la person_1 clé:

--- !ruby/object:Person 
attributes: 
    id: 1 
    name: john 
    age: 18 
    gender: male 

Au lieu de cela si vous avez besoin de stocker chaque attribut comme une clé dans le datastore (pourquoi?) vous devriez assurez-vous que la clé de l'enregistrement de la personne est quelque peu liée à son attribut d'identification, c'est-à-dire l'identifiant d'un ActiveRecord.

Dans ce cas, vous seriez stocker ces clés dans BerkleyDB:

person_1_name="john"; 
person_1_age=18; 
person_1_gender="male"; 
+0

Ceci est proche à la bonne stratégie. Faites attention à la manipulation des objets qui "has_a" d'autres objets. Vous voulez vraiment stocker une référence à l'autre objet la plupart du temps. J'ai fait quelques recherches sur google, et il ne semble pas que Ruby ait une vraie base de données d'objets, ce qui est dommage. Jetez un oeil à KiokuDB Perl ou Elephant CL pour des exemples de la façon de faire ce genre de chose à droite. – jrockway

+0

oui, à droite. Si BerkleyDB n'était pas une exigence stricte, je regarderais aussi Redis: http://code.google.com/p/redis/ car il donne au développeur un vocabulaire beaucoup plus riche de structures de données (listes, ensembles) avec un complexité de calcul bien définie (par exemple, vous connaissez la complexité Big-O des différentes opérations) – LucaM