
Product
Introducing Tier 1 Reachability: Precision CVE Triage for Enterprise Teams
Socketβs new Tier 1 Reachability filters out up to 80% of irrelevant CVEs, so security teams can focus on the vulnerabilities that matter.
Meerkat is an ODM (Object Document Mapper) library designed to replicate the functionality of NodeJS's Mongoose in the .NET ecosystem. π For those unfamiliar, Mongoose is a JavaScript ODM wrapper library that simplifies data access when working with MongoDB. Similarly, Meerkat wraps around the official MongoDB client library for .NET, simplifying common data access patterns.
The name Meerkat is a playful homage to Mongoose, as a meerkat is a type of mongoose. π If you find this library cool or useful, don't forget to give it a βοΈ star!
With the release of version 2.0.0, the underlying MongoDB driver was upgraded to 3.2.0. The library also transitions the base Schema
class to using strongly typed Ids
Thereβs still a lot to be done! Feel free to:
Add the following to your .csproj
file:
<PackageReference Include="meerkat" Version="2.0.0"/>
Run the following command:
Install-Package meerkat
Run the following in your terminal:
dotnet add package meerkat
Before using any of Meerkat's functions, you need to initialize it. This only needs to be done once. π
using meerkat;
...
Meerkat.Connect("<any valid full MongoDB connection string>"); // e.g., mongodb://user:password@server-address:port/database-name?other-options
Ensure youβve declared the necessary namespace at the top of your class file:
using meerkat;
Note: All async methods support CancellationToken
for canceling operations. β³
All models must inherit from the abstract Schema
class. The Schema
class has a an Id
property whose type is determined by the TKey
generic argument. In the example below, the Id
property is of type ObjectId
.
class Student : Schema<ObjectId>
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Student()
{
// Example: Generate an ObjectID (you'd likely use a methode better suited to your Id type)
Id = ObjectId.GenerateNewId();
}
}
To specify a custom collection name or enable timestamp tracking:
[Collection(Name = "Persons", TrackTimestamps = true)]
public class Student : Schema
{
...
}
Meerkat simplifies CRUD operations by combining create and update into a single API. If an entity doesnβt exist, itβs inserted; if it does, itβs updated. π
var student = new Student
{
FirstName = "Olubakinde",
LastName = "Chukumerije"
};
await student.SaveAsync(); // or student.Save(); for synchronous calls
Itβs that simple! π
var student = await Meerkat.FindByIdAsync<Student>(1234); // or Meerkat.FindById<Student>(1234); for sync calls
var student = await Meerkat.FindOneAsync<Student>(x => x.FirstName == "John"); // or Meerkat.FindOne(x => x.LastName == "Jane");
For complex queries, you can access the underlying IQueryable
:
var queryable = Meerkat.Query<Student>();
var students = await queryable
.Where(x => x.FirstName == "Olubakinde")
.ToListAsync();
await Meerkat.RemoveByIdAsync<Student>(1234); // or Meerkat.RemoveById<Student>(1234); for sync calls
await Meerkat.RemoveOneAsync<Student>(x => x.FirstName == "John"); // or Meerkat.RemoveOne(x => x.LastName == "Jane");
await Meerkat.RemoveAsync<Student>(x => x.FirstName == "John"); // or Meerkat.Remove(x => x.LastName == "Jane");
var exists = await Meerkat.ExistsAsync<Student>(); // or Meerkat.Exists<Student>(); for sync calls
var exists = await Meerkat.ExistsAsync<Student>(x => x.FirstName.StartsWith("Ja")); // or Meerkat.Exists<Student>(x => x.FirstName.StartsWith("Ja"));
var count = await Meerkat.CountAsync<Student>(); // or Meerkat.Count<Student>(); for sync calls
var count = await Meerkat.CountAsync<Student>(x => x.FirstName.StartsWith("Ja")); // or Meerkat.Count<Student>(x => x.FirstName.StartsWith("Ja"));
Meerkat allows for bulk upsert operations on collections of entities, both synchronously and asynchronously. π¦
var peter = new Student();
var paul = new Student();
var students = new [] { peter, paul };
await students.SaveAllAsync(); // or students.SaveAll(); for sync calls
This section provides an overview of the custom attributes used to define MongoDB indexes in your model classes. These attributes are applied to fields or properties and are used to generate appropriate indexes in MongoDB. All model classes must inherit from the abstract class Schema<TKey>
.
SingleFieldIndexAttribute
Name
: Specifies the name of the index. If not provided, MongoDB generates a default name.Sparse
: A boolean value indicating whether the index should be sparse. Default is false
.IndexOrder
: Specifies the order of the index. Options are Ascending
, Descending
, or Hashed
.public class User : Schema<Guid>
{
[SingleFieldIndex(Name = "username_index", Sparse = true, IndexOrder = IndexOrder.Ascending)]
public string Username { get; set; }
}
Username
property with an ascending order. The index is sparse, meaning it will only include documents where the Username
field exists.A sparse index only includes documents that have the indexed field. If a document does not contain the indexed field, it is excluded from the index. This can save space and improve performance for fields that are not present in all documents.
A hashed index in MongoDB uses a hash function to compute the value of the indexed field. This is particularly useful for sharding and equality queries but does not support range queries.
UniqueIndexAttribute
Name
: Specifies the name of the index. If not provided, MongoDB generates a default name.Sparse
: A boolean value indicating whether the index should be sparse. Default is false
.public class User : Schema<Guid>
{
[UniqueIndex(Name = "email_unique_index", Sparse = true)]
public string Email { get; set; }
}
Email
property. The index is sparse, meaning it will only include documents where the Email
field exists.CompoundIndexAttribute
Name
: Specifies the name of the index. If two or more fields have the same Name
, they are grouped into a single compound index. Unnamed indexes are grouped into one compound index.IndexOrder
: Specifies the order of the index. Options are Ascending
, Descending
, or Hashed
.public class Order : Schema<Guid>
{
[CompoundIndex(Name = "order_index", IndexOrder = IndexOrder.Ascending)]
public DateTime OrderDate { get; set; }
[CompoundIndex(Name = "order_index", IndexOrder = IndexOrder.Descending)]
public decimal TotalAmount { get; set; }
}
OrderDate
and TotalAmount
properties. The OrderDate
is indexed in ascending order, while the TotalAmount
is indexed in descending order.If multiple fields have the same Name
in the CompoundIndexAttribute
, they are grouped into a single compound index. Unnamed indexes are grouped into one compound index automatically.
GeospatialIndexAttribute
Name
: Specifies the name of the index. If not provided, MongoDB generates a default name.IndexType
: Specifies the type of geospatial index. Options are TwoD
(default) or TwoDSphere
.public class Location : Schema<Guid>
{
[GeospatialIndex(Name = "location_geo_index", IndexType = IndexType.TwoDSphere)]
public double[] Coordinates { get; set; }
}
Explanation: This creates a geospatial index on the Coordinates
property, using the TwoDSphere
index type, which is useful for querying geospatial data on a spherical surface.
What is the Difference Between TwoD and TwoDSphere? π
TwoD
: This index type is used for flat, 2D geospatial data. It is suitable for simple 2D coordinate systems.
TwoDSphere
: This index type is used for geospatial data on a spherical surface (e.g., Earth). It supports more complex queries involving distances, intersections, and other spherical calculations.
Attribute | Purpose | Optional Properties |
---|---|---|
SingleFieldIndex | Single-field index | Name , Sparse , IndexOrder |
UniqueIndex | Unique index | Name , Sparse |
CompoundIndex | Compound index on multiple fields | Name , IndexOrder |
GeospatialIndex | Geospatial index | Name , IndexType |
Hereβs an example of a model class using all the attributes:
public class Product : Schema<Guid>
{
[SingleFieldIndex(Name = "name_index", IndexOrder = IndexOrder.Ascending)]
public string Name { get; set; }
[UniqueIndex(Name = "sku_unique_index", Sparse = true)]
public string SKU { get; set; }
[CompoundIndex(Name = "price_category_index", IndexOrder = IndexOrder.Descending)]
public decimal Price { get; set; }
[CompoundIndex(Name = "price_category_index", IndexOrder = IndexOrder.Ascending)]
public string Category { get; set; }
[GeospatialIndex(Name = "location_geo_index")]
public double[] Location { get; set; }
}
Enjoy using Meerkat! π If you have any questions or feedback, feel free to reach out or contribute to the project. π
FAQs
An ODM for MongoDB
We found that meerkat demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Β It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socketβs new Tier 1 Reachability filters out up to 80% of irrelevant CVEs, so security teams can focus on the vulnerabilities that matter.
Research
/Security News
Ongoing npm supply chain attack spreads to DuckDB: multiple packages compromised with the same wallet-drainer malware.
Security News
The MCP Steering Committee has launched the official MCP Registry in preview, a central hub for discovering and publishing MCP servers.