I have four main kinds: Account, Company, Service and Address. I would like Address entities to be shared between Company and Service entities.
- Account: this is the user account (email, password)
- Company: A business which provide Services (ancestor: Account)
- Service: A service rendered by a Company (ancestor: Company)
- Address: An address (group of fields: street, city, country) of a Company OR a Service (ancestor: Account)
The Challenge: Company and Service entities may have different addresses; after all, a company's address is not necessarily where its services are acquired. Services may have many addresses, since a company may set up different franchises/outlets where its services may be acquired.
I would like to model data in such a way that Addresses can be referenced by either Company or Service entities, or both. I have tried these two approaches:
Let's assume this is the Address model:
class Address(ndb.Model):
street = ndb.StringProperty(required=True)
city = ndb.StringProperty(required=True)
country = ndb.StringProperty(required=True)
Approach 1: Store list of address keys inside Service or Company
class Service(ndb.Model):
title = ndb.StringProperty(required=True)
addresses = ndb.KeyProperty(repeated=True)
class Company(ndb.Model):
name = ndb.StringProperty(required=True)
addresses = ndb.KeyProperty(repeated=True)
Problem: For each page view of Service or Company, I would need to perform additional queries to fetch the their respective addresses. This blows up to be a big expensive problem as our entities grow in number.
Approach 2: Create an AddressMapping entity which forms a relationship between two entities:
class Service(ndb.Model):
title = ndb.StringProperty(required=True)
addresses = ndb.KeyProperty(repeated=True)
class AddressMapping(ndb.Model):
entity = ndb.StringProperty(required=True) # service or company
address = ndb.KeyProperty(repeated=True)
Problem: If a service is disabled/deleted/modified, we need to delete/modify all accompanying AddressMapping entities, or else they will be orphaned. Additional queries still required when viewing pages. This also seems expensive.
These are the two approaches I've come up with; they both seem bad. Any ideas on how I may improve this?