The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
NAME
    DBIx::NoSQL - NoSQL-ish overlay for an SQL database

VERSION
    version 0.0018

SYNOPSIS
        use DBIx::NoSQL;

        my $store = DBIx::NoSQL->connect( 'store.sqlite' );

        $store->set( 'Artist' => 'Smashing Pumpkins' => {
            name => 'Smashing Pumpkins',
            genre => 'rock',
            website => 'smashingpumpkins.com',
        } );

        $store->exists( 'Artist' => 'Smashing Pumpkins' ); # 1

        $store->set( 'Artist' => 'Tool' => {
            name => 'Tool',
            genre => 'rock',
        } );

        $store->search( 'Artist' )->count; # 2

        my $artist = $store->get( 'Artist' => 'Smashing Pumpkins' );

        # Set up a (searchable) index on the name field
        $store->model( 'Artist' )->index( 'name' );
        $store->model( 'Artist' )->reindex;

        for $artist ( $store->search( 'Artist' )->order_by( 'name DESC' )->all ) {
            ...
        }

        $store->model( 'Album' )->index( 'released' => ( isa => 'DateTime' ) );

        $store->set( 'Album' => 'Siamese Dream' => {
            artist => 'Smashing Pumpkins',
            released => DateTime->new( ... ),
        } );

        my $album = $store->get( 'Album' => 'Siamese Dream' );
        my $released = $album->{ released }; # The field is automatically inflated
        print $release->strftime( ... );

DESCRIPTION
    DBIx::NoSQL is a layer over DBI that presents a NoSQLish way to store
    and retrieve data. It does this by using a table called "__Store__".
    Once connected to a database, it will detect if this table is missing
    and create it if necessary

    When writing data to the store, the data (a HASH reference) is first
    serialized using JSON and then inserted/updated via DBIx::Class to
    (currently) an SQLite backend

    Retrieving data from the store is done by key lookup or by searching an
    SQL-based index. Once found, the data is deserialized via JSON and
    returned

    The API is fairly sane, though still beta

USAGE
  $store = DBIx::NoSQL->connect( $path )
    Returns a new DBIx::NoSQL store connected to the SQLite database located
    at $path

    If the SQLite database file at $path does not exist, it will be created

  $store->set( $model, $key, $value )
    Set $key (a string) to $value (a HASH reference) in $model

    If $model has index, this command will also update the index entry
    corresponding to $key

  $value = $store->exists( $model, $key )
    Returns true if some data for $key is present in $model

  $value = $store->get( $model, $key )
    Get $value matching $key in $model

  $value = $store->delete( $model, $key )
    Delete the entry matching $key in $model

    If $model has index, this command will also delete the index entry
    corresponding to $key

  $store->reindex
    Reindex the searchable/orderable data in $store

    This method is smart, in that it won't reindex a model unless the schema
    for $store is different/has changed. That is, if the schema for $store
    is the same as it is in the database, this call will do nothing

    Refer to "Model USAGE" below for more information

  $store->dbh
    Return the DBI database handle for the store, if you need/want to do
    your own thing

Search USAGE
    To search on a model, you must have installed an index on the field you
    want to search on

    Refer to "Model USAGE" for indexing information

  $search = $store->search( $model, [ $where ] )
        $search = $store->search( 'Artist' => { name => { -like => 'Smashing%' } } )

    Return a DBIx::NoSQL::Search object for $model, filtering on the
    optional $where

    An index is required for the filtering columns

    Refer to SQL::Abstract for the format of $where (actually uses
    DBIx::Class::SQLMaker under the hood)

  @all = $search->all
    Returns every result for $search in a list

    Returns an empty list if nothing is found

  $result = $search->next
    Returns the next item found for $search via "$search->cursor"

    Returns undef if nothing is left for $search

  $sth = $search->cursor->sth
    Returns the DBI sth (statement handle) for $search

  $search = $search->search( $where )
    Further refine the search in the same way "$search->where( ... )" does

  $search = $search->where( $where )
        $search = $search->where( { genre => 'rock' } )

    Further refine $search with the given $where

    A new object is cloned from the original (the original $search is left
    untouched)

    An index is required for the filtering columns

    Refer to SQL::Abstract for the format of $where (actually uses
    DBIx::Class::SQLMaker under the hood)

  $search = $search->order_by( $order_by )
        $search->order_by( 'name DESC' )

        $search->order_by([ 'name DESC', 'age' ])

    Return the results in the given order

    A new object is cloned from the original, which is left untouched

    An index is required for the ordering columns

    Refer to SQL::Abstract for the format of $order_by (actually uses
    DBIx::Class::SQLMaker under the hood)

Model USAGE
  $model = $store->model( $model_name )
    Retrieve or create the $model_name model object

  $model->index( $field_name )
        $store->model( 'Artist' )->index( 'name' ) # 'name' is now searchable/orderable, etc.

    Index $field_name on $model

    Every time the store for c<$model> is written to, the index will be
    updated with the value of $field

  $model->index( $field_name, isa => $type )
        $store->model( 'Artist' )->index( 'website', isa => 'URI' )
        $store->model( 'Artist' )->index( 'founded', isa => 'DateTime' )

    Index $field_name on $model as a special type/object (e.g. DateTime or
    URI)

    Every time the store for c<$model> is written to, the index will be
    updated with the deflated value of $field (since JSON can not trivially
    serialize blessed references)

  $model->reindex
    Reindex the $model data in the store after making a field indexing
    change:

        1. Rebuild the DBIx::Class::ResultSource
        2. Drop and recreate the search table for $model
        3. Iterate through all the data for $model, repopulating the search table

    If $model does not have an index, this method will simply return

    To rebuild the index for _every_ model (on startup, for example), you
    can do:

        $store->reindex

In the future
    Create a better interface for stashing and document it

    Wrap things in transactions that need it

    More tests: Always. Be. Testing.

SEE ALSO
    KiokuDB

    DBIx::Class

    DBD::SQLite

AUTHOR
    Robert Krimen <robertkrimen@gmail.com>

COPYRIGHT AND LICENSE
    This software is copyright (c) 2011 by Robert Krimen.

    This is free software; you can redistribute it and/or modify it under
    the same terms as the Perl 5 programming language system itself.