NAME
    Meerkat - Manage MongoDB documents as Moose objects

VERSION
    version 0.011

SYNOPSIS
        use Meerkat;

        my $meerkat = Meerkat->new(
            model_namespace => "My::Model",
            database_name   => "test",
            client_options  => {
                host => "mongodb://example.net:27017",
                username => "willywonka",
                password => "ilovechocolate",
            },
        );

        my $person = $meerkat->collection("Person"); # My::Model::Person

        # create an object and insert it into the MongoDB collection
        my $obj = $person->create( name => 'John' );

        # modify an object atomically
        $obj->update_inc ( likes => 1               ); # increment a counter
        $obj->update_push( tags => [qw/hot trendy/] ); # push to an array

        # find a single object
        my $copy = $person->find_one( { name => 'John' } );

        # get a Meerkat::Cursor for multiple objects
        my $cursor = $person->find( { tags => 'hot' } );

DESCRIPTION
    Meerkat lets you manage MongoDB documents as Moose objects. Your objects
    represent projections of the document state maintained in the database.

    When you create an object, a corresponding document is inserted into the
    database. This lets you use familiar Moose attribute builders and
    validation to construct your documents.

    Because state rests in the database, you don't modify your object with
    accessors. Instead, you issue MongoDB update directives that change the
    state of the document atomically in the database and synchronize the
    object state with the result.

    Meerkat is not an object-relational mapper. It does not offer or manage
    relations or support embedded objects.

    Meerkat is fork-safe. It maintains a cache of MongoDB::Collection
    objects that gets cleared when a fork occurs. Meerkat will transparently
    reconnect from child processes.

USAGE
    Meerkat divides functional responsibilities across six classes:

    *   Meerkat — associates a Perl namespace to a MongoDB connection and
        database

    *   Meerkat::Collection — associates a Perl class within a namespace to
        a MongoDB collection

    *   Meerkat::Role::Document — enhances a Moose object with Meerkat
        methods and metadata

    *   Meerkat::Cursor — proxies a result cursor and inflates documents
        into objects

    *   Meerkat::DateTime — proxies an epoch value with lazy DateTime
        inflation

    *   Meerkat::Types — provides type definition and coercion for
        Meerkat::DateTime

    You define your documents as Moose classes that consume
    Meerkat::Role::Document. This gives them several support methods to
    update, synchronize or remove documents from the database.

    In order to create objects from your model or retrieve them from the
    database, you must first create a Meerkat object that manages your
    connection to the MongoDB database. This is where you specify your
    database host, authentication options and so on.

    You then get a Meerkat::Collection object from the Meerkat object, which
    holds an association between the model class and a collection in the
    database. This class does all the real work of creating, searching,
    updating, or deleting from the underlying MongoDB collection.

    If you use the Meerkat::Collection object to run a query that could have
    multiple results, it returns a Meerkat::Cursor object that wraps the
    MongoDB::Cursor and inflates results into objects from your model.

    Meerkat::DateTime lazily inflates floating point epoch seconds into
    DateTime objects. It's conceptually similar to DateTime::Tiny, but based
    on the epoch seconds returned by the MongoDB client for its internal
    date value representation.

    See Meerkat::Tutorial and Meerkat::Cookbook for more.

ATTRIBUTES
  model_namespace (required)
    A perl module namespace that will be prepended to class names requested
    via the "collection" method. If "model_namespace" is "My::Model", then
    "$meerkat->collection("Baz")" will load and associate the
    "My::Model::Baz" class in the returned collection object.

  database_name (required)
    A MongoDB database name used to store all collections generated via the
    Meerkat object and its collection factories. Unless a "db_name" is
    provided in the "client_options" attribute, this database will be the
    default for authentication.

  client_options
    A hash reference of MongoDB::MongoClient options that will be passed to
    its "connect" method.

    Note: The "dt_type" will be forced to "undef" so that the MongoDB client
    will provide time values as epoch seconds. See the Meerkat::Cookbook for
    more on dealing with dates and times.

  collection_namespace
    A perl module namespace that will be be used to search for custom
    collection classes. The "collection_namespace" will be prepended to
    class names requested via the "collection" method. If
    "collection_namespace" is "My::Collection", then
    "$meerkat->collection("Baz")" will load and use "My::Collection::Baz"
    for constructing a collection object. If "collection_namespace" is not
    provided or if no class is found under the namespace (or if it fails to
    load), then collection objects will be constructed using
    Meerkat::Collection.

METHODS
  new
        my $meerkat = Meerkat->new(
            model_namespace => "My::Model",
            database_name   => "test",
            client_options  => {
                host => "mongodb://example.net:27017",
                username => "willywonka",
                password => "ilovechocolate",
            },
        );

    Generates and returns a new Meerkat object. The "model_namespace" and
    "database_name" attributes are required.

  collection
        my $person = $meerkat->collection("Person"); # My::Model::Person

    Returns a Meerkat::Collection factory object or possibly a subclass if a
    "collection_namespace" attribute has been provided. A single parameter
    is required and is used as the suffix of a class name provided to the
    Meerkat::Collection "class" attribute.

  mongo_collection
        my $coll = $meerkat->mongo_collection("My_Model_Person");

    Returns a raw MongoDB::Collection object from the associated database.
    This is used internally by Meerkat::Collection and is not intended for
    general use.

EXCEPTION HANDLING
    Unless otherwise specified, all methods throw exceptions on error either
    directly or by not catching errors thrown by MongoDB classes.

WARNINGS AND CAVEATS
    Your objects are subject to the same limitations as any MongoDB
    document.

    Most significantly, because MongoDB uses the dot character as a field
    separator in queries (e.g. "foo.bar"), you may not have the dot
    character as the key of any hash in your document.

        # this will fail
        $person->create( emails => { "dagolden@example.com" => "primary" } );

    Be particularly careful with email addresses and URLs.

RATIONALE
    Working with raw MongoDB documents as pure data structures is a bit
    painful and annoying. There are some existing libraries that attempt to
    make life easier, but I found them deficient in one way or another.

    I tried Mongoose first. I had problems when trying to work with multiple
    databases and doing any sort of authentication and it doesn't seem very
    actively maintained. MongoDBX::Class (discussed next) has some
    additional Mongoose critiques. Mongoose is about 1000 lines of code
    split across fourteen modules.

    Next I looked at MongoDBx::Class. In many ways, it works much more like
    the basic MongoDB classes. What stopped me cold was that it requires
    inserts to be done with a raw data structure. That means no defaults,
    validation, lazy building and other stuff that I like about Moose. It
    does offer some support making updates easier, and I've adapted that
    approach for Meerkat. MongoDBx::Class is about 800 lines of code split
    across fifteen modules.

    Both offer a relational model. While a noble goal, I'm suspicious of
    applying relational data models to a document-oriented database like
    MongoDB that doesn't have transactions. MongoDB offers atomic *document*
    updates, so I decided to focus Meerkat on that alone.

    Mongoose and MongoDBx also support defining embedded documents. I
    haven't decided if that's necessary — and it adds quite a bit of
    complexity — so I haven't implemented it in Meerkat.

    There are other MongoDB-based modules that I found and dismissed:

    *   KiokuDB::Backend::MongoDB, but see the Mongoose critique of it

    *   MongoDB::Simple, which is too simple to do what I want

    *   MongoDBx::Tiny, which hurts my eyes

    *   MongoDBI, "scheduled for a rewrite in the coming months" for the
        last year

    Conceptually, Meerkat is a bit similar to Mongoose, but less ambitious.
    (A meerkat is a smaller member of the mongoose family, after all.) It
    adopts some of the features I liked from MongoDBx::Class.

    Meerkat focuses on:

    *   Multiple database support

    *   Easy configuration of database connections

    *   Fork safety

    *   Simplicity and (to the extent possible) Moosey-ness

    *   A document-centric data model

    Because it is less ambitious, Meerkat is smaller and less complex,
    currently about 480 lines of code split across six modules.

SEE ALSO
  Meerkat documentation
    *   Meerkat::Tutorial

    *   Meerkat::Cookbook

  Other MongoDB resources
    *   MongoDB::MongoClient

    *   MongoDBx::Class

    *   Mongoose

SUPPORT
  Bugs / Feature Requests
    Please report any bugs or feature requests through the issue tracker at
    <https://github.com/dagolden/Meerkat/issues>. You will be notified
    automatically of any progress on your issue.

  Source Code
    This is open source software. The code repository is available for
    public review and contribution under the terms of the license.

    <https://github.com/dagolden/Meerkat>

      git clone https://github.com/dagolden/Meerkat.git

AUTHOR
    David Golden <dagolden@cpan.org>

COPYRIGHT AND LICENSE
    This software is Copyright (c) 2013 by David Golden.

    This is free software, licensed under:

      The Apache License, Version 2.0, January 2004

