# Elixir db model

I have designed this model which is very flexible. For example, you can create asset types, assets and combinations of them infinitely. It is the front end to a Python Pyramid website, so all the validation and business logic is handled by the web app.

However, not being a db guy, I have this sneaking suspicion that the schema totally sucks. There may be performance issues etc that I haven't foreseen etc.

class Asset(Entity):
has_field('TimeStamp', Unicode, nullable=False)
has_field('Modified', Unicode)
belongs_to('AssetType', of_kind='AssetType', inverse='Assets')
has_many('Values', of_kind='Value', inverse='Asset')
Assets = ManyToMany('Asset')

@property
def Label(self):
if self.AssetType:
for f in self.AssetType.Fields:
if f.Label:
if self.Values:
for v in self.Values:
if v.Field.Name == f.Name:
return v.Value

def __repr__(self):
return '<Asset | %s>' % self.id

class AssetType(Entity):
has_field('Name', Unicode, primary_key=True)
has_field('Plural', Unicode)
has_many('Assets', of_kind='Asset', inverse='AssetType')
has_many('Fields', of_kind='Field', inverse='AssetType')

class Value(Entity):
has_field('Value', Unicode)
belongs_to('Asset', of_kind='Asset', inverse='Values')
belongs_to('Field', of_kind='Field', inverse='Values')

class Field(Entity):
has_field('Name', Unicode)
has_field('Unique', Unicode, default=False)
has_field('Label', Boolean, default=False)
has_field('Searchable', Boolean, default=False)
has_field('Required', Boolean, default=False)
has_many('Values', of_kind='Value', inverse='Field')
belongs_to('FieldType', of_kind='FieldType', inverse='Fields')
belongs_to('AssetType', of_kind='AssetType', inverse='Fields')

class FieldType(Entity):
has_field('Name', Unicode, primary_key=True)
has_field('Label', Unicode, unique=True)
has_many('Fields', of_kind='Field', inverse='FieldType')


You've reinvented a database inside a database. Basically, the Asset/AssetType is a simulation of a database inside a database which will as a result be slow. Also, you are going to spend a lot of effort reimplementing database features.

You could do this by using a NoSQL database which is designed to handle less structured data might be a good idea. Or you could create a table for each asset type which will perform better.

@property
def Label(self):
if self.AssetType:
for f in self.AssetType.Fields:
if f.Label:
if self.Values:
for v in self.Values:
if v.Field.Name == f.Name:
return v.Value


That's really nested which is bad sign. I suggest something like:

@property
def Label(self):
if self.AssetType:
label = self.AssetType.Label
field = self.find_field(label)
if field:
return field.Value


Or if you use the Null Object pattern:

@property
def Label(self):
return self.find_field(self.AssetType.label).Value

• Thanks @Winston, you're right about the db in the db idea. I'm a bit scared of locking the schema because the business rules here are changing rapidly. I had a look at CouchDB which is very flexible, but I can't get my head around map/reduce. I'll take a look at NoSQL. Failing that, I think I'll take your advice and just structure it. Thanks for the rewrites above too, I learned a lot.
– MFB
Aug 5, 2011 at 4:37
• ok CouchDB IS NoSQL... and it's documentation has come a long way since I first looked into it. CouchDB is exactly what I need for a db in this case, and as it turns out, it will probably suffice as a web server too. Woot!
– MFB
Aug 7, 2011 at 22:26
• @MFB, The fact that your business rules are changing shouldn't drive you to NoSQL. In that case, I'm just going to constantly update the schema. Aug 10, 2011 at 12:52
• you're right. It's not my only reason for looking at Couch. The more I look at Couch though, the more sense it makes to me, for this application at least. Almost everything in my business model can be described as an asset (or Document). The flexibility to continually add and subtract keys is just a huge bonus.
– MFB
Aug 11, 2011 at 13:22