ArangoDB

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

  
      # Create new document
      $foo->save({ x => 42, y => { a => 1, b => 2, } });
      $foo->save({ x => 1, y => { a => 1, b => 10, } });
      $foo->name('new_name'); # rename the collection
  
      # Create hash index.
      $foo->ensure_hash_index([qw/x y/]);
  
      # Simple query
      my $cursor = $db->('new_name')->by_example({ b => 2 });
      while( my $doc = $cursor->next ){
          # do something
      }
  
      # AQL
      my $cursor2 = $db->query( 
          'FOR u IN users FILTER u.age > @age SORT u.name ASC RETURN u' 
      )->bind( { age => 19 } )->execute();
      my $docs = $cursor2->all;

DESCRIPTION
    This module is an ArangoDB's REST API client for Perl.

    ArangoDB is a universal open-source database with a flexible data model
    for documents, graphs, and key-values.

    More information: <http://www.arangodb.org/>

SUPPORT API VERSION

lib/ArangoDB.pm  view on Meta::CPAN

  
  # Create new document
  $foo->save({ x => 42, y => { a => 1, b => 2, } });
  $foo->save({ x => 1, y => { a => 1, b => 10, } });
  $foo->name('new_name'); # rename the collection
  
  # Create hash index.
  $foo->ensure_hash_index([qw/x y/]);
  
  # Simple query
  my $cursor = $db->('new_name')->by_example({ b => 2 });
  while( my $doc = $cursor->next ){
      # do something
  }
  
  # AQL
  my $cursor2 = $db->query( 
      'FOR u IN users FILTER u.age > @age SORT u.name ASC RETURN u' 
  )->bind( { age => 19 } )->execute();
  my $docs = $cursor2->all;

=head1 DESCRIPTION

This module is an ArangoDB's REST API client for Perl.

ArangoDB is a universal open-source database with a flexible data model for documents, graphs, and key-values.

More information: L<http://www.arangodb.org/>

=head1 SUPPORT API VERSION

lib/ArangoDB/Collection.pm  view on Meta::CPAN

=pod

=head1 METHODS FOR SIMPLE QUERY HANDLING

=head2 all([$options])
 
Send 'all' simple query. Returns instance of L<ArangoDB::Cursor>.

This will return all documents of in the collection.

    my $cursor = $collection->all({ limit => 100 });

$options is query option(HASH reference).The attributes of $options are:

=over 4

=item limit

The maximal amount of documents to return. (optional)

=item skip

lib/ArangoDB/Collection.pm  view on Meta::CPAN

}

=pod

=head2 by_example($example[,$options])

Send 'by_example' simple query. Returns instance of L<ArangoDB::Cursor>.

This will find all documents matching a given example.

    my $cursor = $collection->by_example({ age => 20 });

=over 4

=item $example

The exmaple.

=item $options

Query option(HASH reference).The attributes of $options are:

lib/ArangoDB/Collection.pm  view on Meta::CPAN

=pod

=head2 range($attr,$lower,$upper[,$options])

Send 'range' simple query. Returns instance of L<ArangoDB::Cursor>.

It looks for documents in the collection with attribute between two values.

Note: You must declare a skip-list index on the attribute in order to be able to use a range query.

    my $cursor = $collection->range('age', 20, 29, { closed => 1 } );

=over 4

=item $attr 

The attribute path to check.

=item $lower 

The lower bound.

lib/ArangoDB/Collection.pm  view on Meta::CPAN


=pod

=head2 near($latitude,$longitude[,$options])

Send 'near' simple query. Returns instance of L<ArangoDB::Cursor>.

The default will find at most 100 documents near a given coordinate. 
The returned list is sorted according to the distance, with the nearest document coming first.

    $cursor = $collection->near(0,0, { limit => 20 } );

=over 4

=item $latitude 

The latitude of the coordinate.

=item $longitude 

The longitude of the coordinate.

lib/ArangoDB/Collection.pm  view on Meta::CPAN


=pod

=head2 within($latitude,$longitude,$radius[,$options])

Send 'within' simple query. Returns instance of L<ArangoDB::Cursor>.

This will find all documents with in a given radius around the coordinate (latitude, longitude).
The returned list is sorted by distance.

    $cursor = $collection->within(0,0, 10 * 1000, { distance => 'distance' } );

=over 4

=item $latitude

The latitude of the coordinate.

=item $longitude

The longitude of the coordinate.

lib/ArangoDB/Constants.pm  view on Meta::CPAN

# Update policies
use constant {
    POLICY_LAST  => 'last',
    PILICY_ERROR => 'error',
};

# API
use constant {
    API_DOCUMENT       => '/_api/document',
    API_COLLECTION     => '/_api/collection',
    API_CURSOR         => '/_api/cursor',
    API_EDGE           => '/_api/edge',
    API_EDGES          => '/_api/edges',
    API_KEY            => '/_api/key/',
    API_KEYS           => '/_api/keys/',
    API_EXAMPLE        => '/_api/simple/by-example',
    API_QUERY          => '/_api/query',
    API_EXPLAIN        => '/_api/explain',
    API_INDEX          => '/_api/index',
    API_IMPORT         => '/_api/import',
    API_SIMPLE_ALL     => '/_api/simple/all',

lib/ArangoDB/Cursor.pm  view on Meta::CPAN

                return [ map { !ref($_) ? $_ : _clone($_) } @$orig ];
            }
            elsif ( $reftype eq 'HASH' ) {
                return { map { !ref($_) ? $_ : _clone($_) } %$orig };
            }
        };
    }
}

sub new {
    my ( $class, $conn, $cursor ) = @_;
    my $len = 0;
    if ( defined $cursor->{result} && ref( $cursor->{result} ) eq 'ARRAY' ) {
        $len = scalar @{ $cursor->{result} };
    }
    my $self = bless {
        connection => $conn,
        id         => $cursor->{id},
        length     => $len,
        count      => $cursor->{count},
        has_more   => $cursor->{hasMore},
        position   => 0,
        result     => $cursor->{result} || [],
    }, $class;
    if ( $self->{id} ) {
        $self->{_api_path} = API_CURSOR . '/' . $self->{id};
    }
    weaken( $self->{connection} );
    return $self;
}

sub next {
    my $self = shift;

lib/ArangoDB/Cursor.pm  view on Meta::CPAN

    my $self = shift;
    return unless $self->{has_more};
    eval {
        my $res = $self->{connection}->http_put( $self->{_api_path}, {} );
        $self->{has_more} = $res->{hasMore};
        $self->{length}   = scalar( @{ $res->{result} } );
        $self->{result}   = $res->{result};
        $self->{position} = 0;
    };
    if ($@) {
        $self->_server_error_handler( $@, 'Failed to get next batch cursor(%d)' );
    }
    return 1;
}

sub delete {
    my $self = shift;
    eval { $self->{connection}->http_delete( $self->{_api_path} ) };
    if ($@) {
        $self->_server_error_handler( $@, 'Failed to delete cursor(%d)' );
    }
}

sub _server_error_handler {
    my ( $self, $error, $message ) = @_;
    my $msg = sprintf( $message, $self->id );
    if ( ref($error) && $error->isa('ArangoDB::ServerException') ) {
        $msg .= ':' . ( $error->detail->{errorMessage} || q{} );
    }
    croak $msg;

lib/ArangoDB/Cursor.pm  view on Meta::CPAN



=pod

=head1 NAME

ArangoDB::Cursor - An ArangoDB Query Cursor hanlder

=head1 SYNOPSIS

    my $cursor = $db->query('FOR u IN users RETURN u')->execute();
    my @docs;
    while( my $doc = $cursor->next ){
        push @docs, $doc;
    }

=head1 DESCRIPTION

Instance of ArandoDB Query Cursor.

=head1 METHODS

=head2 new()

Constructor.

=head2 next()

Returns next document(Instance of L<ArangoDB::Document>).

=head2 all()

Rreturns all documents in the cursor.(ARRAY reference).

The cursor on the server will be deleted implicitly.

=head2 delete()

Delete a cursor.

The cursor will automatically be destroyed on the server when the client has retrieved all documents from it. 
The client can also explicitly destroy the cursor at any earlier time using this method.

=head1 AUTHOR

Hideaki Ohno E<lt>hide.o.j55 {at} gmail.comE<gt>

=cut

lib/ArangoDB/Statement.pm  view on Meta::CPAN

=head1 SYNOPSIS

    use ArangoDB;
    
    my $db = ArangoDB->new(
        host => 'localhost',
        port => 8529,
    );
  
    my $sth = $db->query('FOR u IN users FILTER u.active == true RETURN u');
    my $cursor = $sth->execute({ 
        do_count => 1, 
        batch_size => 10,
    });
    while( my $doc = $cursor->next() ){
        # do something
    }
  
    # Use bind variable
    my $documents = $db->query(
        'FOR u IN users FILTER u.age >= @age SORT u.name ASC RETURN u'
    )->bind( age => 18 )->execute()->all;

=head1 DESCRIPTION

lib/ArangoDB/Statement.pm  view on Meta::CPAN

Instance of ArangoDB::Connection.

=item $query 

AQL statement.

=back

=head2 execute($options)

Execute AQL query and returns cursor(instance of L<ArangoDB::Cursor>).

$options is query options.The attributes of $options are:

=over 4

=item batch_size

Maximum number of result documents to be transferred from the server to the client in one roundtrip (optional). 

=item do_count

t/05_query.t  view on Meta::CPAN

    }

    my $expects = [ { name => 'Baz', age => 11 }, { name => 'Bar', age => 20 }, { name => 'John Doe', age => 42 }, ];
    is_deeply \@docs, $expects;

    my $docs2
        = $db->query('FOR u IN users FILTER u.age > @age SORT u.age ASC RETURN u')->bind( age => 10 )->execute->all;
    is_deeply [ map { $_->content } @$docs2 ], $expects;
};

subtest 'delete cursor' => sub {
    my $db  = ArangoDB->new($config);
    my $sth = $db->query('FOR u IN users FILTER u.age > @age SORT u.name ASC RETURN u');
    $sth->bind( age => 10 );
    my $cur = $sth->execute( { batch_size => 2, } );
    $cur->delete;
    like exception {
        while ( my $doc = $cur->next() ) {
        }
    }, qr/^Failed to get next batch cursor/;

    like exception {
        $cur->delete;
    }, qr/^Failed to delete cursor/;

    like exception {
        my $guard = mock_guard(
            'ArangoDB::Connection' => {
                http_delete => sub {die}
            }
        );
        $cur->delete;
    }, qr/^Failed to delete cursor/;

};

subtest 'parse query' => sub {
    my $db    = ArangoDB->new($config);
    my $binds = $db->query('FOR u IN users SORT u.name ASC RETURN u')->parse();
    is scalar @$binds, 0;

    $binds = $db->query('FOR u IN users FILTER u.age > @age SORT u.name ASC RETURN u')->parse();
    is_deeply $binds, [qw/age/];

t/05_query.t  view on Meta::CPAN

    }, qr/^Failed to parse query/;
};

subtest 'explain query' => sub {
    my $db   = ArangoDB->new($config);
    my $plan = $db->query('FOR u IN users SORT u.name ASC RETURN u')->explain();
    ok $plan && ref($plan) eq 'ARRAY';
    like exception { $db->query('FOR u IN users SORT u.name ASC RETURN ')->explain(); }, qr/^Failed to explain query/;
};

subtest 'cursor' => sub {
    my $db   = ArangoDB->new($config);
    my $conn = $db->{connection};
    my $cur  = ArangoDB::Cursor->new( $conn, {} );
    isa_ok $cur, 'ArangoDB::Cursor';

    $cur = ArangoDB::Cursor->new( $conn, { result => {} } );
    ok $cur;

    $cur = ArangoDB::Cursor->new(
        $conn,



( run in 0.278 second using v1.01-cache-2.11-cpan-4d50c553e7e )