Skip to content

lumio-medical/lumio-record

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Lumio Record

GitHub Workflow Status Maven Central Repository javadoc GitHub

This library provides utilities for handling document versioning and sourcing in a MongoDB database.

Implementations found in this package will shouldn't be tied to any specific Lumio project.

Note: This library is considered as "in beta" and as such significant API changes may occur without prior warning.

I. Installation

Add the following in your pom.xml:

<dependency>
    <groupId>com.lumiomedical</groupId>
    <artifactId>lumio-record</artifactId>
    <version>0.1.1</version>
</dependency>

II. Notes on Structure and Design

The code in this library was initially found in the lumio-core repository. As such, although most of its components were, from their inception, designed to be "stand-alone" and not tied to specific business needs, some components can be less mature as a stand-alone than they could be.

Now that this is out of the way, this library features three groups of components:

  • the com.lumiomedical.record package contains tools for defining versioned entities
  • the com.lumiomedical.record.store package contains contracts and implementations for storing versioned entities using the noleme-store library
  • the com.lumiomedical.record.source package contains tools for defining sourced entities (ie. entities with references to one or several external sources via a foreign unique identifier), note that a Record is a Sourceable

Further documentation of these three groups is underway.

TODO

III. Usage

Here is a simple example of what this library looks like when in use:

Patient patient;
/* find the patient using their unique identifier */
patient = patientStore.find(someUid);
/* ..this is equivalent to doing */
patient = patientStore.find(someUid, Referential.now());

/* ..this time we want an earlier version */
patient = patientStore.find(someUid, Referential.at(parse("2018-01-01T00:00:00.00Z")));

List<Patient> records;
/* find all records for the patient with this unique identifier */
records = patientStore.list(List.of(someUid), Referential.any());

/* ..this time we only want versions from a given timeframe */
records = patientStore.list(
    List.of(someUid),
    Referential.between(parse("2020-10-15T00:00:00.00Z"), parse("2020-11-01T00:00:00.00Z"))
);

/* insert a record version at the present time */
patientStore.put(patient);
/* ..or at a given date */
patientStore.put(patient, Referential.at(parse("2020-11-05T00:00:00.00Z")));

Now, let's look a bit closer at what it looks like when creating a Record entity and its store.

First, we'll start by defining the record entity, let's say it's a very basic Patient record:

public class Patient extends Record<Patient>
{
    public String firstName;
    public String lastName;
    public Instant birthDate;
}

We now have to define a store interface contract and an implementation for it.

Start by creating an interface, we'll call it PatientStore, and make it extend the RecordStore interface.

This interface is where all possible requests are declared, the RecordStore contract already provides the most common ones but if you have any specific behaviour (eg. custom aggregation pipes), this is the place to declare them. In our case, we just want the default behaviour, so we'll use RecordStore and be done with it.

public interface PatientStore extends RecordStore<Patient> {}

Now that we have the interface, we want a MongoDB implementation ; note that it extends the MongoDBRecordStore abstract class, which provides implementations for the RecordStore contract, as well as a host of utility methods:

public class MongoDBPatientStore extends MongoDBRecordStore<Patient> implements PatientStore
{
    /* Note that we are given a parent constructor which expects a MongoDBClient and a Factory, we'll talk about them in a moment */
    public MongoDBPatientStore(MongoDBClient client, Factory<BasicDBObject, Patient> factory)
    {
        super(client, factory);
    }
    
    @Override
    protected String getCollectionName()
    {
        /* Here, we return the name of the collection in the mongodb database, it can be anything we want */
        return "patient";
    }
}

Now that we have our PatientStore and its MongoDB incarnation, the final step is creating a Factory. The factory class is responsible for the translation between the Patient POJO and its MongoDB document, here is what it could look like for Patient.

public class PatientFactory implements Factory<BasicDBObject, Patient>
{
    @Override
    public Patient build(BasicDBObject input)
    {
        /* This bit is responsible for the build of a Patient POJO out of a MongoDB document */
        var patient = new Patient();
        patient.firstName = input.getString("first_name");
        patient.lastName = input.getString("last_name");
        patient.birthDate = DBObjects.getInstantOrNull(input, "birth_date");
        return patient;
    }

    @Override
    public BasicDBObject transcript(Patient input)
    {
        /* This bit is responsible for the transcription of a Patient POJO into a MongoDB document */
        return new BasicDBObject()
            .append("first_name", input.firstName)
            .append("last_name", input.lastName)
            .append("birth_date", input.birthDate)
        ;
    }
}

There are more efficient ways to do that but for the time being let's stick to basic.

We have everything now, so let's do a few requests:

PatientStore store = new MongoDBPatientStore(new MongoDBClient("my_db", "localhost", 27017), new PatientFactory());

var patient = new Patient();
patient.firstName = "Arnold";
patient.lastName = "Weber";
patient.birthDate = Instant.parse("2001-01-01T00:00:00.00Z");

/* Let's insert it at his birthdate */
store.put(patient, Referential.at(patient.birthDate));

/* Let's change his first name */
patient.firstName = "Bernard";

/* Let's insert this some time later */
store.put(patient, Referential.at(Instant.parse("2020-01-01T00:00:00.00Z")));

/* This should print Bernard */
System.out.println(store.find(patient.getUid()).firstName);
/* This should print Arnold */
System.out.println(store.find(patient.getUid(), Referential.at(Instant.parse("2010-01-01T00:00:00.00Z"))).firstName);

TODO

IV. Dev Installation

This project will require you to have the following:

  • Java 13+
  • Git (versioning)
  • Maven (dependency resolving, publishing and packaging)

About

A library providing utilities for handling document versioning and sourcing in a MongoDB database

Resources

License

Stars

Watchers

Forks

Languages