Skip to content

Examples

RezaNajafian edited this page Dec 8, 2025 · 1 revision

This page shows end-to-end examples of how to use MongoHelper annotations together with schematics and operations.

We will build a small User model and show:

  • How to annotate the model and fields
  • How to define indexes
  • How to define a constructor for deserialization
  • How to create a schematic
  • How to register the schematic and use OperationsGroup

Note: The code below is example code for documentation purposes. You can adapt names and types to your own project.


1. User Model with Annotations

package com.example.mongo;

import net.clydo.mongo.annotations.OrmModel;
import net.clydo.mongo.annotations.OrmField;
import net.clydo.mongo.annotations.OrmUnique;
import net.clydo.mongo.annotations.OrmModelUnique;
import net.clydo.mongo.annotations.OrmModelIndex;
import net.clydo.mongo.annotations.OrmConstructor;
import net.clydo.mongo.annotations.OrmParameter;
import org.bson.types.ObjectId;

@OrmModel("users")
@OrmModelUnique({"email", "tenant"}) // compound unique index on (email, tenant)
@OrmModelIndex({"tenant", "created_at"}) // non-unique index to speed up queries
public class User {

    @OrmField("_id")
    private ObjectId id;

    @OrmField("email")
    @OrmUnique // single-field unique index on email
    private String email;

    @OrmField("tenant")
    private String tenant;

    @OrmField("created_at")
    private long createdAt;

    @OrmField("age")
    private int age;

    @OrmConstructor(strict = true)
    public User(
            @OrmParameter("_id") ObjectId id,
            @OrmParameter("email") String email,
            @OrmParameter("tenant") String tenant,
            @OrmParameter("created_at") long createdAt,
            @OrmParameter("age") int age
    ) {
        this.id = id;
        this.email = email;
        this.tenant = tenant;
        this.createdAt = createdAt;
        this.age = age;
    }

    // getters/setters or records/immutables as you prefer
}

What this configuration does

  • @OrmModel("users")
    • Maps the class to the users collection.
  • @OrmField("...")
    • Maps each field to the given MongoDB document field name.
    • _id must be of type ObjectId.
  • @OrmUnique on email
    • Creates a unique index on email.
  • @OrmModelUnique({"email", "tenant"})
    • Creates a compound unique index (email, tenant).
  • @OrmModelIndex({"tenant", "created_at"})
    • Creates a non-unique compound index (tenant, created_at).
  • @OrmConstructor(strict = true) + @OrmParameter
    • Tells MongoHelper exactly how to construct User from database documents.
    • Ensures all @OrmField fields are covered by constructor parameters.

2. Schematic for the User Model

package com.example.mongo;

import net.clydo.mongo.OrmSchematic;
import org.bson.codecs.configuration.CodecRegistry;

import java.util.List;

public class UserSchematic implements OrmSchematic {

    @Override
    public String getDatabaseName() {
        return "app_db";
    }

    @Override
    public List<Class<?>> getModelClasses() {
        return List.of(User.class);
    }

    @Override
    public List<Class<?>> getTypeClasses() {
        return List.of();
    }

    @Override
    public List<Class<? extends Enum<?>>> getEnumClasses() {
        return List.of();
    }

    @Override
    public List<CodecRegistry> handleCodecRegistry(List<CodecRegistry> registries) {
        // Optionally customize codec registries here.
        return registries;
    }
}

When UserSchematic is registered, MongoHelper will:

  • Build metadata for the User model
  • Configure the codec registry for app_db
  • Create the users collection (if needed)
  • Create all indexes declared by @OrmUnique, @OrmModelUnique, and @OrmModelIndex
  • Create an OperationsGroup<User> and cache it

3. Registering the Schematic and Using OperationsGroup

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import net.clydo.mongo.MongoHelper;
import net.clydo.mongo.operations.OperationsGroup;

public class UserExampleApp {

    public static void main(String[] args) {
        try (MongoClient client = MongoClients.create("mongodb://localhost:27017")) {
            MongoHelper helper = MongoHelper.create(client);

            // Register schematic
            helper.register(UserSchematic.class);

            // Get operations group for User
            OperationsGroup<User> users = helper.get(User.class);

            // Now you can use users.create(), users.find(), users.update(), etc.
            // Example (pseudocode - adapt to your actual operations API):

            User newUser = new User(
                    null, // _id will be generated by MongoDB
                    "john@example.com",
                    "tenant1",
                    System.currentTimeMillis(),
                    30
            );

            // CREATE (insert)
            users.create()
                    // .one(newUser);
                    ;

            // FIND (by email)
            users.find()
                    // .where(eq("email", "john@example.com"))
                    ;

            // UPDATE (set age)
            users.update()
                    // .where(eq("email", "john@example.com"))
                    // .set("age", 31)
                    ;
        }
    }
}

The exact method names on create(), find(), update(), etc. depend on your concrete implementation of the operation classes. The code above shows the overall pattern.


4. Minimal Example Without Constructor Annotation

If you prefer, you can start with a simpler model that does not use @OrmConstructor and @OrmParameter. In that case, MongoHelper will fall back to a default constructor selection.

@OrmModel("simple_users")
public class SimpleUser {

    @OrmField("_id")
    private ObjectId id;

    @OrmField("name")
    private String name;

    @OrmField("email")
    @OrmUnique
    private String email;

    // default constructor required
    public SimpleUser() {
    }

    // getters/setters
}

You can still:

  • Register this model via a schematic
  • Get OperationsGroup<SimpleUser>
  • Use create(), find(), etc.

5. Tips for Using Annotations Correctly

  • Make sure @OrmField aliases are unique within a model.
  • Use the same aliases in @OrmModelIndex, @OrmModelUnique, and @OrmParameter.
  • When using @OrmConstructor(strict = true), ensure all @OrmField fields appear in the constructor with @OrmParameter.
  • Keep your schema definitions in one place by grouping related models into the same OrmSchematic.

For more details about each annotation, see the Annotations page.

Clone this wiki locally