Flaksator – storing core resources in noSQL

As I’d already mentioned, I’m going to store all Flaksator’s resources in noSQL database. I’d already decided to use lightweight (it’s just package / DLL) implementation.

And before I start I owe one explanation to English speaking visitors. Flaksator is just a play-on-words: original library responsible for managing Polish flection rules I’d called “Fleksator”, from Polish “fleksja” meaning “flection”. Then, my – more or less – funny application that randomized brutal, blasphemous lyrics I’d called “Flaksator”, which differs only by one, yet meaningful letter from library name. The Polish word “flak” means “guts, entrails, bowels” in English. Pleas enjoy my creativity 😉

I know I have several types of resources in the Flaksator:

  1. Simple lists of strings (title verses templates, verse templates, song static elements)
  2. Simple dictionary items (translations, enumerations, word categories)
  3. Definitions – complicated dictionaries (mainly postfixes lists)
  4. Word definitions themself (will be covered in next article).


It’s very tempting to just use CRUD repository pattern here. I’know that this is considered to be sort of anti-pattern (i.e. article by Ben Morris and many more). However I do not care 😉 Why?
I REALLY have only few operations on my data:

  • Read-all, Save-all for lists and dictionaries.
  • Read-all, Save/Update-one for word definitions.
  • Perhaps Delete command for definitions, but it will rather be Disable.

Yes, that is all. I do not consider updating single elements for lists or dictionaries (well, maybe, if I need). But for sure I will never require any complex Retrieve or update operations. Therefore I’d just decided to have very simple interfaces for my operations…

public interface IDictionariesRepository
{
    IEnumerable<string> GetTitles();
    IEnumerable<string> GetTitleExtenders();

    void SaveTitles(IEnumerable<string> titles);
    void SaveTitleExtenders(IEnumerable<string> titleExtenders);
}

I’d started with some naive implementation. I went fine until implementing SaveStrings() method…

internal class LiteDictionariesRepository : IDictionariesRepository
{
    private const string TITLES = @"TITLES";
    private const string TITLE_EXTENDERS = @"TITLE_EXTENDERS";

    private readonly LiteDatabase _db;

    public LiteDictionariesRepository(LiteDatabase db)
    {
        _db = db;
    }

    public IEnumerable<string> GetTitles()
    {
        return GetStrings(TITLES);
    }       

    public IEnumerable<string> GetTitleExtenders()
    {
        return GetStrings(TITLE_EXTENDERS);
    }

    public void SaveTitles(IEnumerable<string> titles)
    {
        SaveStrings(TITLES, titles);
    }        

    public void SaveTitleExtenders(IEnumerable<string> titleExtenders)
    {
        SaveStrings(TITLE_EXTENDERS, titleExtenders);
    }

    private IEnumerable<string> GetStrings(string collectionKey)
    {
        return _db.GetCollection<StringWrapper>(collectionKey).FindAll().Select(w => w.Value);
    }

    private void SaveStrings(string collectionKey, IEnumerable<string> items)
    {
        var collection = _db.GetCollection<StringWrapper>(collectionKey);
        collection.Delete(wrapper => true); // delete all
        collection.Insert(items.Select(s => new StringWrapper(s)));
    }
}

(Where StringWrapper was just a plain container for one string.)

But this was bad. I did not like this. It seems that my simple concept must be revisited. I expect collection.Delete() operation to be both inefficient and insecure…
I do not like the idea of giving every string unique id and create entity either…

I decided then to wrap whole list as one entity, identified by list name:

public class StringWrapper
{
    public StringWrapper()
    {
            
    }

    public StringWrapper(string key, IEnumerable<string> strings)
    {
        Key = key;
        Strings = strings.ToArray();
    }

    [BsonId]
    public string Key { get; set; }

    public string[] Strings { get; set; }
}

And then also change how storage access is being implemented, by extending a bit LiteDictionariesRepository class:

private const string LISTS_IDENTIFIER = @"LISTS";

private IEnumerable<string> GetStrings(string collectionKey)
{
    var wrapper = _db.GetCollection<StringWrapper>(LISTS_IDENTIFIER)
        .Find(w => w.Key == collectionKey).SingleOrDefault();
    if (wrapper != null)
    {
        return wrapper.Strings;
    }

    return new string[0];
}

private void SaveStrings(string collectionKey, IEnumerable<string> items)
{
    var collection = _db.GetCollection<StringWrapper>(LISTS_IDENTIFIER);
    var wrapper = _db.GetCollection<StringWrapper>(LISTS_IDENTIFIER)
        .Find(w => w.Key == collectionKey).SingleOrDefault();
    if (wrapper == null)
    {
        wrapper = new StringWrapper(collectionKey, items);
        collection.Insert(wrapper);
    }
    else
    {
        wrapper.Strings = items.ToArray();
        collection.Update(wrapper);
    }
}

The same way I’m going to treat song verses – however maybe dividing them into few different collections, like PreparedTemplates, ClearVerses and TemplatesUnderConstruction to distinguish different phazes of their preparation.
And then I also need to store my dictionaries… This requires a bit more thinking, so I’m just going tu push it further to the next post 😉

Of course, there might arise question – why I’m even bothering with repositories for such simple operations? The answer is, that I’m trying to separate my code from noSQL implementation details, in case I will have to move to Azure (or else) someday and need to replace LiteDb with MongoDB or something else. I will then just replace only all repository implementations, that dos not sound like much work ;-).

And, some nice, newly generated song (“The cooling-down hot-dog in the light of darkness”). You might like to use google Translator – It’s quite good, but still missed few times, but it doesn’t matter anyway 😉

STYGNĄCY HOT-DOG W ŚWIETLE MROKU

(Refren)
Wyrąbałem sobie kreaturę wyżynając tysiąc zakrzepic,
Teraz siedzę wśród kostnic plugawych, wszędzie ścierniska i wrzody.
Nie było czasu na myślenie, chwyciłem więc mój skrzep,
Takie już moje usposobienie, poleci dziś groźna stopa.
Bez przebaczenia, padasz już francuski,
Przegrałeś, zginąłeś, to nie są żarty.

Noc drew ułatwi asfalt,
To nadziana bardzo prawica.
Wnet usłyszałem omam upiora,
Zabić mi kazał grzesznika nikczemnika.
Nastąpił flak zastanawiania,
Nadszedł już czas zabijania.
By spełnić ssącą krowę moją,
Zabrałem smoczek zdegradowanego upiora.

(Przejście)

(Refren)
Wyrąbałem sobie kreaturę wyżynając tysiąc zakrzepic,
Teraz siedzę wśród kostnic plugawych, wszędzie ścierniska i wrzody.
Nie było czasu na myślenie, chwyciłem więc mój skrzep,
Takie już moje usposobienie, poleci dziś groźna stopa.
Bez przebaczenia, padasz już francuski,
Przegrałeś, zginąłeś, to nie są żarty.

Jesteś w mej pochodni, czas zmówić stratowanego omamu,
To już Twój cmentarz, pochłonie Cię dziada poranek.
Chwili dłużej nie zwlekałem,
Pożerać umywalki bardzo chciałem.
Dnia tego tłustego, lobotomia mnie opętała,
Zabijać, gwałcić, palić, tak oto mi kazała.
Zapach Twych drew, jatka pokojówek,
Te oto dręczą mnie stonogi.

(Interludium)

(Refren)
Wyrąbałem sobie kreaturę wyżynając tysiąc zakrzepic,
Teraz siedzę wśród kostnic plugawych, wszędzie ścierniska i wrzody.
Nie było czasu na myślenie, chwyciłem więc mój skrzep,
Takie już moje usposobienie, poleci dziś groźna stopa.
Bez przebaczenia, padasz już francuski,
Przegrałeś, zginąłeś, to nie są żarty.

(Włochate Solo)

Rzucam się na Ciebie z ścieżką,
Atakuję tu przed trumną.
Na trawie widać zbezczeszczony ślad, obok niego zaś Twoje ciało,
Wszędzie posoka, żółte flaki, niewiele już z Ciebie zostało.
Nastąpił chodnik zastanawiania,
Nadszedł już ryk zabijania.
Dostrzegłem okno, stonogę białasa,
Nie, nie zawiodę dziś mego grabarza.

(Refren)
Wyrąbałem sobie kreaturę wyżynając tysiąc zakrzepic,
Teraz siedzę wśród kostnic plugawych, wszędzie ścierniska i wrzody.
Nie było czasu na myślenie, chwyciłem więc mój skrzep,
Takie już moje usposobienie, poleci dziś groźna stopa.
Bez przebaczenia, padasz już francuski,
Przegrałeś, zginąłeś, to nie są żarty.

(Interludium)

(Straszny Łoskot)

Mam odbyt deliryczny u mego kurzu,
Dziś zasmakuje apokaliptycznego rogu.
Chrześcijanin mój, nieubłagany Chrześcijanin, nauczył mnie, jak labolatoria zgrabnie wyrywa się.
Mojej zjawy muszę bronić, widziałem dziś Indianina,
Obetnę księżyc mu, wydłubię jelita, zabiję kwadratowego syna.
Nadszedł więc czas na kwiat kazirodczy,
Wybiegłem z krwawicą na ulice Warszawy.

W jęku konaru stała sprawiedliwość,
Labolatorium wrzoda tak się tam poniewiera.
Niewiasta była elektryczna, jak doktorowa ma,
Dziś swoje alibi ktoś mi odda.

Roughly translated:

The cooling-down hot-dog in the light of darkness

(Chorus)
Cut down a creature notching thousands thrombosis,
Now I sit among the filthy morgues, everywhere stubble and ulcers.
There was no time to think, so I grabbed my clot
Such know my disposition, will fly today a dangerous rate.
Without forgiveness, you fall already French,
You lost, you died, it’s not a joke.

    Night of woods facilitated by the asphalt,
    It is stuffed with a right hand.
    Soon I heard the ghost hallucination,
    I had to kill the wicked villain.
    There was bowel of thinking,
    It’s time to kill.
    To fulfill my sucking cow,
    I took a pacifier of degraded wraith.

(Transition)

(Chorus)
Cut down a creature Notching thousand thrombosis,
Now I sit among the filthy morgues, everywhere stubble and ulcers.
There was no time to think, so I grabbed my clot
Such know my disposition, will fly today a dangerous rate.
Without forgiveness, you fall already French,
You lost, you died, it’s not a joke.

    You are in my torch, time to collude trampled delusion,
    It’s your graveyard, you will be consumed by grandfather’s morning.
    Not any longer I delayed,
    I wanted to devour sinks.
    Day of the fat, lobotomy me obsessed,
    Kill, rape, burn, so here I was told.
    The smell of thy wood, shambles maids,
    These here bother me centipedes.

(Interlude)

(Chorus)
Cut down a creature Notching thousand thrombosis,
Now I sit among the filthy morgues, everywhere stubble and ulcers.
There was no time to think, so I grabbed my clot
Such know my disposition, will fly today a dangerous rate.
Without forgiveness, you fall already French,
You lost, you died, it’s not a joke.

(Hairy Solo)

    I throw myself on you with the path,
    I attack here before the coffin.
    On the grass you can see defiled mark next to it and your body,
    Everywhere gore, yellow guts, little has been with you.
    There was a sidewalk wondering,
    It is already the roar of killing.
    I saw the window, centipede of white man,
    No, I do not fail today my gravedigger.

(Chorus)
Cut down a creature Notching thousand thrombosis,
Now I sit among the filthy morgues, everywhere stubble and ulcers.
There was no time to think, so I grabbed my clot
Such know my disposition, will fly today a dangerous rate.
Without forgiveness, you fall already French,
You lost, you died, it’s not a joke.

(Interlude)

(Scary noise)

    I have delusory anus with my dust,
    Today it gonna taste apocalyptic corner.
    Christian my unrelenting Christian, taught me how to skilfully extract laboratories.
    I have to defend my ghosts, I have seen today, Indian,
    I’ll cut him to the moon, will pick intestines, I’ll kill the son of a square.
    It is time to flower incestuous,
    I ran out of the bleed on the streets of Warsaw.

The limb was groaning justice,
Laboratory abscess so there scorns.
The woman was electric, as my doctor’s wife,
Today, his alibi someone is going to pass to me.