mongo_document 1.6.5 copy "mongo_document: ^1.6.5" to clipboard
mongo_document: ^1.6.5 copied to clipboard

A code generator for MongoDB-backed Dart models using @MongoDocument annotations - build type-safe, maintainable backend layers.

pub package license

Table of Contents #

  1. Overview

  2. Getting Started

  3. Usage

  4. Configuration & Conventions

  5. Troubleshooting

  6. Contributing

  7. License

Overview #

mongo_document simplifies interaction between Dart classes and MongoDB using mongo_dart. It generates zero-boilerplate, type-safe CRUD methods, query builders, and supports cross-collection lookups and projections. It works seamlessly with both freezed and plain Dart classes.

This package allows you to:

  • Perform type-safe CRUD operations directly from your Dart classes.
  • Respect Dart naming conventions (e.g., camelCase) while mapping to your MongoDB schema (e.g., snake_case).
  • Define complex queries, projections, and cross-collection lookups with minimal boilerplate.

Getting Started #

Prerequisites #

  • Dart SDK ≥ 3.0
  • A running MongoDB instance (local or remote)
  • MongoDB server version ≥ 3.6

Installation #

Add to pubspec.yaml:

dependencies:
  freezed_annotation: ">=2.4.4 <4.0.0"
  json_annotation: ^4.9.0
  mongo_document_annotation: ^1.6.4

dev_dependencies:
  build_runner: ^2.4.14
  freezed: ">=2.5.8 <4.0.0"
  json_serializable: ^6.9.3
  mongo_document: ^1.6.4

Then:

dart pub get

Initialization #

Configure your MongoDB connection once in your application entrypoint:

import 'package:mongo_document_annotation/mongo_document_annotation.dart';

Future<void> main() async {
  await MongoConnection.initialize('mongodb://localhost:27017/mydb');

  // Graceful shutdown
  ProcessSignal.sigint.watch().listen((_) async {
    await MongoDbConnection.shutdown();
    exit(0);
  });
  ProcessSignal.sigterm.watch().listen((_) async {
    await MongoDbConnection.shutdown();
    exit(0);
  });
}

Usage #

Using Freezed Classes #

import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:mongo_document_annotation/mongo_document_annotation.dart';

part 'post.freezed.dart';
part 'post.g.dart';
part 'post.mongo_document.dart';

@MongoDocument(collection: 'posts')
@freezed
abstract class Post with _$Post {
  @JsonSerializable(fieldRename: FieldRename.snake, explicitToJson: true)
  const factory Post({
    @ObjectIdConverter() @JsonKey(name: '_id') ObjectId? id,
    String? body,
    User? author,
    @DateTimeConverter() DateTime? createdAt,
    @DateTimeConverter() DateTime? updatedAt,
  }) = _Post;

  factory Post.fromJson(Map<String, dynamic> json) => _$PostFromJson(json);
}

Using Regular Classes (No Freezed) #

import 'package:json_annotation/json_annotation.dart';
import 'package:mongo_document_annotation/mongo_document_annotation.dart';

part 'post.mongo_document.dart';

/// Post (Regular Class)
/// This class shows how to use mongo_document without freezed.
/// The user must implement copyWith(), fromJson(), and toJson().
@MongoDocument(collection: 'posts')
@JsonSerializable(fieldRename: FieldRename.snake, explicitToJson: true)
class Post {
  final String? body;
  final User? author;
  final ObjectId? id;

  Post({
    @ObjectIdConverter() @JsonKey(name: '_id') this.id,
    this.body,
    this.author,
  });

  Post copyWith({ObjectId? id, String? body, User? author}) {
    return Post(
      id: id ?? this.id,
      body: body ?? this.body,
      author: author ?? this.author,
    );
  }

  factory Post.fromJson(Map<String, dynamic> json) => throw UnimplementedError();

  Map<String, dynamic> toJson() => throw UnimplementedError();
}

CRUD Examples #

// Create & Save
final post = await Post(body: 'Hello world').save();

// Batch Save
await Posts.saveMany([Post(body: 'A'), Post(body: 'B')]);

// Update via copyWith then save
await post?.copyWith(body: 'Updated').save();

// Targeted updateOne
await Posts.updateOne(
  (p) => p.body.eq('Hello world'),
  body: 'Updated via updateOne'
);

Lookups & Projections #

Cross-collection lookup example: fetch posts with the latest 3 comments each.

final posts = await Posts.findMany(
  (p) => p.body.contains("Hello"),
  lookups: [
    Lookup(
      from: Comments.collection,
      as: "comments",
      limit: 3,
      localField: "_id",
      foreignField: "post",
    ),
  ],
);

Projecting fields of related documents: fetch posts with author details.

final posts = await Posts.findMany(
  (p) => p.body.contains("Hello"),
  projections: [PostAuthorProjections()]
);

Combining lookups and projections:

final posts = await Posts.findMany(
  (p) => p.body.contains("Hello"),
  lookups: [
    Lookup(
      from: Comments.collection,
      as: "comments",
      limit: 3,
      localField: "_id",
      foreignField: "post",
    ),
  ],
  projections: [PostAuthorProjections(), PostProjection()]
);

This fetches each post, includes the author information, and the latest 3 comments.

Configuration & Conventions #

  • Ensure _id is annotated with @ObjectIdConverter() and @JsonKey(name: '_id').
  • Use @JsonSerializable(fieldRename: FieldRename.snake) to map camelCase fields to MongoDB style.
  • Nested @MongoDocument types generate projection helpers automatically.

Troubleshooting #

Add to analysis_options.yaml:

analyzer:
  errors:
    invalid_annotation_target: ignore

Contributing #

See CONTRIBUTING.md for guidelines.

License #

MIT License — see LICENSE.

2
likes
135
points
261
downloads

Publisher

unverified uploader

Weekly Downloads

A code generator for MongoDB-backed Dart models using @MongoDocument annotations - build type-safe, maintainable backend layers.

Repository (GitHub)
View/report issues

Topics

#codegen #mongodb #backend #dart #annotations

Documentation

Documentation
API reference

License

MIT (license)

Dependencies

analyzer, build, collection, dart_style, json_annotation, mongo_dart, mongo_document_annotation, path, pub_semver, recase, source_gen

More

Packages that depend on mongo_document