meerkat 2.0.2

dotnet add package meerkat --version 2.0.2
                    
NuGet\Install-Package meerkat -Version 2.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="meerkat" Version="2.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="meerkat" Version="2.0.2" />
                    
Directory.Packages.props
<PackageReference Include="meerkat" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add meerkat --version 2.0.2
                    
#r "nuget: meerkat, 2.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package meerkat@2.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=meerkat&version=2.0.2
                    
Install as a Cake Addin
#tool nuget:?package=meerkat&version=2.0.2
                    
Install as a Cake Tool

Meerkat

Build, Test & Coverage codecov NuGet Version License: MIT

Meerkat is an ODM (Object Document Mapper) for MongoDB in .NET. It wraps the official MongoDB driver and simplifies common data access patterns, modelling, querying, persistence, and indexing with a clean, strongly-typed API.

Installation

.NET CLI

dotnet add package meerkat

Package Manager Console

Install-Package meerkat

.csproj


<PackageReference Include="meerkat" Version="2.0.1"/>

Setup

Call Connect once at application startup, before any other Meerkat operation:

using meerkat;

Meerkat.Connect("mongodb://user:password@host:port/database-name");

Defining Models

All models must inherit from Schema<TId>, where TId is the type of the document's unique identifier. The Id property is automatically mapped as the MongoDB _id field.

using meerkat;
using MongoDB.Bson;

public class Student : Schema<ObjectId>
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public Student()
    {
        Id = ObjectId.GenerateNewId();
    }
}

Common ID types include ObjectId, Guid, string, and int any type that implements IEquatable<T>.

Collection configuration

Apply the [Collection] attribute to control the collection name and timestamp tracking:

[Collection(Name = "persons", TrackTimestamps = true)]
public class Student : Schema<ObjectId>
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}
  • Name - overrides the default collection name. Without this attribute, Meerkat uses a pluralized, lowercased version of the class name (e.g., Studentstudents).
  • TrackTimestamps - when true, Meerkat automatically sets CreatedAt on first save and updates UpdatedAt on every subsequent save.

Querying

All static query methods on Meerkat require two type parameters: the schema type and the ID type.

Find by ID

var student = await Meerkat.FindByIdAsync<Student, ObjectId>(id);
// sync:
var student = Meerkat.FindById<Student, ObjectId>(id);

Find one by predicate

var student = await Meerkat.FindOneAsync<Student, ObjectId>(x => x.FirstName == "Ada");
// sync:
var student = Meerkat.FindOne<Student, ObjectId>(x => x.LastName == "Lovelace");

Omitting the predicate returns the first document in the collection.

Find many by predicate

var students = await Meerkat.FindAsync<Student, ObjectId>(x => x.LastName == "Lovelace");
// sync:
var students = Meerkat.Find<Student, ObjectId>(x => x.LastName == "Lovelace");

Omitting the predicate returns all documents.

LINQ queries

For complex queries, use Query<TSchema, TId>() to get a LINQ-compatible IQueryable:

var results = await Meerkat.Query<Student, ObjectId>()
    .Where(x => x.FirstName.StartsWith("A"))
    .OrderBy(x => x.LastName)
    .ToListAsync();

Persistence

Save and SaveAsync perform an upsert: inserting the document if it does not exist, or replacing it if it does. The match is done on Id.

var student = new Student { FirstName = "Ada", LastName = "Lovelace" };

await student.SaveAsync();
// sync:
student.Save();

Bulk Persistence

To save multiple entities in a single batched operation, use the SaveAll / SaveAllAsync extension methods from the meerkat.Collections namespace:

using meerkat.Collections;

var students = new[] { new Student(), new Student() };

await students.SaveAllAsync<Student, ObjectId>();
// sync:
students.SaveAll<Student, ObjectId>();

Removal

Remove by ID

await Meerkat.RemoveByIdAsync<Student, ObjectId>(id);
// sync:
Meerkat.RemoveById<Student, ObjectId>(id);

Remove first match

await Meerkat.RemoveOneAsync<Student, ObjectId>(x => x.FirstName == "Ada");
// sync:
Meerkat.RemoveOne<Student, ObjectId>(x => x.FirstName == "Ada");

Remove all matches

await Meerkat.RemoveAsync<Student, ObjectId>(x => x.LastName == "Lovelace");
// sync:
Meerkat.Remove<Student, ObjectId>(x => x.LastName == "Lovelace");

Counting

// total count
long total = await Meerkat.CountAsync<Student, ObjectId>();

// conditional count
long count = await Meerkat.CountAsync<Student, ObjectId>(x => x.FirstName.StartsWith("A"));

// sync variants
long total = Meerkat.Count<Student, ObjectId>();
long count = Meerkat.Count<Student, ObjectId>(x => x.FirstName.StartsWith("A"));

Existence Checks

bool any = await Meerkat.ExistsAsync<Student, ObjectId>();
bool match = await Meerkat.ExistsAsync<Student, ObjectId>(x => x.FirstName == "Ada");

// sync variants
bool any = Meerkat.Exists<Student, ObjectId>();
bool match = Meerkat.Exists<Student, ObjectId>(x => x.FirstName == "Ada");

Indexing

Apply index attributes to model properties to have Meerkat automatically create the appropriate MongoDB indexes.

Single-field index

public class User : Schema<Guid>
{
    [SingleFieldIndex(Name = "username_idx", Sparse = true, IndexOrder = IndexOrder.Ascending)]
    public string Username { get; set; }
}
Property Default Description
Name auto Custom index name
Sparse false Excludes documents missing the field
IndexOrder Ascending Ascending, Descending, or Hashed

Unique index

public class User : Schema<Guid>
{
    [UniqueIndex(Name = "email_idx", Sparse = true)]
    public string Email { get; set; }
}
Property Default Description
Name auto Custom index name
Sparse false Excludes documents missing the field

Compound index

Fields sharing the same Name value are grouped into a single compound index:

public class Order : Schema<Guid>
{
    [CompoundIndex(Name = "order_idx", IndexOrder = IndexOrder.Ascending)]
    public DateTime OrderDate { get; set; }

    [CompoundIndex(Name = "order_idx", IndexOrder = IndexOrder.Descending)]
    public decimal TotalAmount { get; set; }
}

Fields without a Name are grouped together into one unnamed compound index.

Geospatial index

public class Location : Schema<Guid>
{
    [GeospatialIndex(Name = "coords_idx", IndexType = GeospatialIndexType.TwoDSphere)]
    public double[] Coordinates { get; set; }
}
Property Default Description
Name auto Custom index name
IndexType TwoD TwoD for flat geometry, TwoDSphere for spherical (Earth-surface) queries

Index summary

Attribute Scope Key properties
SingleFieldIndex Single property Name, Sparse, IndexOrder
UniqueIndex Single property Name, Sparse
CompoundIndex Multiple properties Name (groups fields), IndexOrder
GeospatialIndex Single property Name, IndexType

Data Transformations

Apply [Lowercase] or [Uppercase] to string properties to have their values automatically transformed before each save. Both attributes are restricted to string properties and throw InvalidAttributeException if applied to any other type.

public class User : Schema<Guid>
{
    [Lowercase]
    public string Email { get; set; }

    [Uppercase]
    public string CountryCode { get; set; }
}

Lifecycle Hooks

Override PreSave and PostSave on any model to run custom logic before or after persistence:

public class Student : Schema<ObjectId>
{
    public string FirstName { get; set; }

    public override void PreSave()
    {
        // runs after timestamp updates and transformations, before the database write
        FirstName = FirstName?.Trim();
    }

    public override void PostSave()
    {
        // runs after the database write completes
    }
}

Breaking Changes

v2.0.0

  • The MongoDB driver was upgraded to 3.x.
  • The base class Schema was replaced by the generic Schema<TId>, requiring an explicit ID type parameter on all models and on all static Meerkat methods.

Contributing

Issues and pull requests are welcome at github.com/bolorundurowb/meerkat.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.2 91 5/17/2026
2.0.1 148 2/26/2026
2.0.0 345 2/26/2025
1.1.0 1,377 2/2/2025
1.0.19 276 2/2/2025
1.0.18 328 8/17/2024
1.0.17 397 11/5/2023
1.0.16 236 11/5/2023
1.0.13 5,741 6/8/2022
1.0.12 723 2/4/2022
1.0.11 623 2/4/2022
1.0.10 495 1/3/2022
1.0.9 549 10/27/2021
1.0.8 512 10/27/2021
1.0.7 530 10/26/2021
1.0.6 505 10/25/2021
1.0.5 480 10/23/2021
1.0.4 491 10/11/2021
Loading failed

- Update dependencies