Model entities implement the EntityInterface, which combines: - the StorableEntityInterface, which allows them to call upon - a storage controller, implementing the StorageControllerInterface StorableEntityInterface StorageController() StorageControllerInterface The storage controllers implement the StorageControllerInterface, which defines: - the collection holding the data - the data id: the name of the possibly multiple data keys to combine to identify an entity - the driver to use to access the data StorageControllerInterface Collection() string Id() []string Driver() *StorageDriverInterface The storage drivers implement the StorageDriver interface, which defines: - the underlying opaque go-level object - database enumeration The storage driver instances are likely to be shared objects, hence may not contain any per-controller or per-entity information, and cannot be embedded in storage controllers, but must be standalone StorageDriverInterface DbDriver() interface{} Databases() []DatabaseInterface DropDatabase(db DatabaseInterface) MakeDatabase() DatabaseInterface Storage drivers may exist in multiple instances, to address multiple connections to different DB servers. Multiple driver instance MUST NOT address the same server, to avoid consistency issues. Databases implement the DatabaseInterface, which defines: - collection enumeration - collection access by name - collection deletion DatabaseInterface Collections() []string Collection(name) CollectionInterface DropCollection(name string) Collections implement the Collection interface, which defines: - document (row) CRUD - truncation CollectionInterface Truncate() Document(id IdInterface) Find(crit CriteriumInterface) QueryInterface Criteria implement the CriteriumInterface CriteriumInterface Fields() []string Queries are promises implementing the QueryInterface. They are meant to be used as a fluent interface, like: cursor, err := coll.Find(someCriteria).Order(someOrdering).Execute() QueryInterface Execute() ExecutedQueryInterface Order([]OrderSpecification) QueryInterface Skip(offset int64) QueryInterface Limit(count int64) QueryInterface Count() int64 Fields() []string Note that Fields() will only return the fields specifically requested. If the query does not specify fields (like SQL "SELECT *" or MongoDB "coll.find({})", it will return empty. Executed queries implement the ExecutedQueryInterface. They provide access to the non-executed query, a cursor, and the fields available in all documents (which) may need cursor unrolling and be very costly) ExecutedQueryInterface Cursor() CursorInterface Query() QueryInterface Fields() []string For selection queries returning multiple documents, the cursor will typically be iterated. Selection queries returning a single document are just a case of 1 being a value of n. Count queries and modification queries return a cursor to available data, like count, affected documents or last insert id. The available columns depend on the query type, hence the use of Fields(). Every database driver provides support for queries which this set of interfaces cannot build. Applications needing to build such queries, can use DbDriver() to access the database driver for their custom needs, losing database-independence. They can limit the db-dependent part by building an ExecutedQueryInterface from their results, at which point code can resume db independence. Bridge packages can provide this mapping.