go-ike / ike

1 stars 1 forks source link

Model for CouchDB and Cloudant #7

Open mateusnroll opened 7 years ago

mateusnroll commented 7 years ago

Models are essential to persisting data, which almost any application needs. Since ike is built on Javascript, it makes sense to focus on non-relational databases first.

The first one we're attacking is CouchDB and its super-saiyan counterpart Cloudant. Both will have a dedicated model for persisting and retrieving data.

Basic information

Database views

Views are design documents specifically designed to retrieve information from the database.

A view file should look like:

class SomeView extends KubusView {
    constructor() {
        this.viewName = 'someOtherName'; // Optional, default would be class name
    }

    map(doc) {
        emit(doc.id, doc.balance);
    }

    reduce(key, values, rereduce) {
        return sum(values);
    }
}

Cloudant search indexes

Search indexes should be their own file type, and reside in a separate file (but within dbviews folder). The file should be name filenmame.search.js.

A search index file should look like:

class SomeSearchIndex extends KubusSeach {
    constructor() {
        this.viewName = 'someOtherName'; // Optional, default would be class name
    }

    map(doc) {
        index('name', doc.name, {store: true});
    }
}

To query a seach index, just use the method search:

const SomeSearchIndex = require('dbviews/some.search.js');

SomeSearchIndex.search('name:john')
    .then(person => res.send(person))
    .catch(error => res.status(500).send(error));

Database models

Model superclass Model classes are logical representations of the document, and the superclass should provide a foundation for building on top of.

class Some extends KubusModel {}

Document validation Cloudant and CouchDB will accept any document, and it's the job of the application to ensure consistency. Having model validations will aid just that.

class Some extends KubusModel {
    constructor() {
        this.validation = {
            name: String,
            age: Integer,
            birthDate: Date,
            Something: Object,
            anotherSomething: {
                name: String,
                region: string
            }
        };

        this.validationOptions = {strict: true, stopOnFirstError: true};
    }
}

Easy document retrieval Getting documents should be easy enough, specially when I know exactly what I'm looking for.

const Sample = require('models/sample.model.js');
Sample.get('abcf-1234-hfds').then(...);

Edit and delete documents Editing and deleting documents should be left to the instance, which will be able to know exaclty what to do with the document and its state.

const Sample = require('models/sample.model.js');
Sample.get('abcf-1234-hfds').then(
    sample => {
        sample.name = "Something";
        return sample.save;
    },
).then(
    saveSuccess => res.status(201).send();
).catch(
    error => res.status(400).send(error);
);

Lifecycle events It should be possible to hook into a specific lifecycle point and perform actions. Main lifecycle events we should be looking into:

mateusnroll commented 7 years ago

It's almost done! Working on the tests now 👍 pasted_image_at_2016_12_20_01_13_pm