mbdavid / LiteDB

LiteDB - A .NET NoSQL Document Store in a single data file
http://www.litedb.org
MIT License
8.5k stars 1.24k forks source link

[CONTRIBUTION] Schema Migrations for LiteDb - introducing LiteDbMigrations #2532

Open ssteiner opened 1 month ago

ssteiner commented 1 month ago

I was recently working with migrations in other NoSql Databases - and quickly made my first contributions toward migration frameworks. I then looked into how things would work for LiteDb. Had a long look at Jonas Kamsker's LiteDb.Migrations, didn't like that I needed to create X different versions (I generally adapt my models and be done with it - the different MigrationObject versions show that both concepts work), and figured I'd write something of my own based on concepts I learned from the migration tools for RavenDb and MongoDb. So here's LiteDbMigrations.

It is based on the idea of patching a collection rather than updating individual documents - so I'm using a lot of UpdateMany in my migrations. You can also insert documents, delete documents, even drop or rename collections easily.

Here's a sample on how you'd add/remove a property

[Migration(20240731100610)]
internal class AddNullableBool : DatabaseMigration
{
    private readonly string collectionName = LiteDbConstants.MigrationObjectCollection;

    public override void Up(ILiteDatabase db)
    {
        var col = db.GetCollection(collectionName);
        int nbRows = col.UpdateMany("{ IsDefault: true }", "_id > 0");
    }

    public override void Down(ILiteDatabase db)
    {
        int nbRows = RemoveProperty(db, nameof(MigrationObject_V2.IsDefault), collectionName);
    }
}

it's still early stages, but if you find it useful, if you have ideas for it, hit me up. I might just publish it as a package if there's sufficient interest.

JKamsker commented 1 month ago

My library is able to migrate the whole database at once. But the main idea of it was to be able to upgrade documents on the fly.

To your library: Looks good. Tooling such as dotnet-ef would be great which automatically figures out the migrations for you and applies them if neccessary. I spared myself from it till an unspecified future point in time 😅

ssteiner commented 1 month ago

You know, I was thinking about the dotnet-ef commands as well after writing it and looking through my migrations again before posting. However, I'd expect that to take more time than I invested so far. Plus, I'd have to store the schema for every migration somewhere in order to calculate the differences (like the class derived from ModelSnapshot that dotnet-ef creates).

I was actually thinking I'd be less diligent when writing migrations than when using EFCore - a new property that gets set on some documents, and then you revert to an older version, there's no immediate harm if the property lingers around in the DB, and any update will kill it anyway (I presume at least.. haven't tried that) - it only gets critical if you re-add as another type. So I'll probably end up writing migrations just for renaming properties and moving properties. But I guess if I get fed up writing manual migrations I might just consider some kind of simple automation.