meerkat 2.0.2
dotnet add package meerkat --version 2.0.2
NuGet\Install-Package meerkat -Version 2.0.2
<PackageReference Include="meerkat" Version="2.0.2" />
<PackageVersion Include="meerkat" Version="2.0.2" />
<PackageReference Include="meerkat" />
paket add meerkat --version 2.0.2
#r "nuget: meerkat, 2.0.2"
#:package meerkat@2.0.2
#addin nuget:?package=meerkat&version=2.0.2
#tool nuget:?package=meerkat&version=2.0.2
Meerkat
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.,Student→students).TrackTimestamps- whentrue, Meerkat automatically setsCreatedAton first save and updatesUpdatedAton 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
Schemawas replaced by the genericSchema<TId>, requiring an explicit ID type parameter on all models and on all staticMeerkatmethods.
Contributing
Issues and pull requests are welcome at github.com/bolorundurowb/meerkat.
| Product | Versions 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. |
-
.NETStandard 2.0
- MongoDB.Driver (>= 3.8.1)
- mongo-url-parser (>= 1.1.0)
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 |
- Update dependencies