From 0425b9a802b54d223c616c678f3af326cc6adf1c Mon Sep 17 00:00:00 2001 From: Mainframe2008 Date: Fri, 1 Feb 2013 12:44:18 +0100 Subject: Added comments for searching using secondary indexes --- lib/Net/Riak/Role/REST/Search.pm | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'lib/Net/Riak/Role') diff --git a/lib/Net/Riak/Role/REST/Search.pm b/lib/Net/Riak/Role/REST/Search.pm index b83e3d4..7e74af5 100644 --- a/lib/Net/Riak/Role/REST/Search.pm +++ b/lib/Net/Riak/Role/REST/Search.pm @@ -1,6 +1,7 @@ package Net::Riak::Role::REST::Search; use Moose::Role; use JSON; +use Data::Dumper; #ABSTRACT: Search interface @@ -73,4 +74,24 @@ sub setup_indexing { JSON::decode_json($http_response->content); } +sub i2search { + my $self = shift; + my %params = @_; + my $request; + + my $org_prefix = $self->prefix; + + $request = $self->new_request('GET', [ + 'buckets', + $params{bucket}, + 'index', + $params{index}, + $params{key} + ] + ); + + my $http_response = $self->send_request($request); + JSON::decode_json($http_response->content)->{keys}; +} + 1; -- cgit 1.4.1 From 2fd683a151a9a4bdaf64d44468fbde4fa5226602 Mon Sep 17 00:00:00 2001 From: Mainframe2008 Date: Fri, 1 Feb 2013 12:46:04 +0100 Subject: Added support for searching with secondary indexes --- lib/Net/Riak.pm | 2 +- lib/Net/Riak/Object.pm | 29 +++++++++++++++++++++++++++++ lib/Net/Riak/Role/REST.pm | 2 +- lib/Net/Riak/Role/REST/Object.pm | 20 ++++++++++++++++++-- lib/Net/Riak/Search.pm | 16 ++++++++++++++++ 5 files changed, 65 insertions(+), 4 deletions(-) (limited to 'lib/Net/Riak/Role') diff --git a/lib/Net/Riak.pm b/lib/Net/Riak.pm index d4f8ef9..06caba8 100644 --- a/lib/Net/Riak.pm +++ b/lib/Net/Riak.pm @@ -14,7 +14,7 @@ has client => ( is => 'rw', isa => Client_T, required => 1, - handles => [qw/is_alive all_buckets server_info stats search setup_indexing/] + handles => [qw/is_alive all_buckets server_info stats search i2search setup_indexing/] ); sub BUILDARGS { diff --git a/lib/Net/Riak/Object.pm b/lib/Net/Riak/Object.pm index 7148d4f..8e48dcb 100644 --- a/lib/Net/Riak/Object.pm +++ b/lib/Net/Riak/Object.pm @@ -5,6 +5,7 @@ package Net::Riak::Object; use Moose; use Scalar::Util; use Net::Riak::Link; +use Data::Dumper; with 'Net::Riak::Role::Replica' => {keys => [qw/r w dw/]}; with 'Net::Riak::Role::Base' => {classes => @@ -23,6 +24,9 @@ has vtag => (is => 'rw', isa => 'Str'); has content_type => (is => 'rw', isa => 'Str', default => 'application/json'); has location => ( is => 'rw', isa => 'Str' ); has _jsonize => (is => 'rw', isa => 'Bool', lazy => 1, default => 1); + +has i2indexes => ( is => 'rw', isa => 'HashRef' ); + has links => ( traits => ['Array'], is => 'rw', @@ -69,6 +73,31 @@ sub store { $self->client->store_object($w, $dw, $self); } +sub i2index { + my($self, $args) = @_; + + if ( defined($args) ) { + my %args = %{$args}; + my $ref = undef; + if ( defined($self->i2indexes) ) { $ref = $self->i2indexes; } + foreach my $i (keys %args) + { + + #$i = lc($i); + print $i,"\n"; + if ( defined($args{$i}) && length($args{$i}) > 0 ) + { + $ref->{$i} = $args{$i}; + + } else { + delete $ref->{$i}; + } + } + $self->i2indexes($ref); + } + $self->i2indexes; +} + sub status { my ($self) = @_; warn "DEPRECATED: status method will be removed in the 0.17 release, please use ->client->status."; diff --git a/lib/Net/Riak/Role/REST.pm b/lib/Net/Riak/Role/REST.pm index 92ea3ae..dc8222a 100644 --- a/lib/Net/Riak/Role/REST.pm +++ b/lib/Net/Riak/Role/REST.pm @@ -70,7 +70,7 @@ sub new_request { # makes a HTTP::Request returns and stores a HTTP::Response sub send_request { my ($self, $req) = @_; - + $self->http_request($req); my $r = $self->useragent->request($req); diff --git a/lib/Net/Riak/Role/REST/Object.pm b/lib/Net/Riak/Role/REST/Object.pm index fc45f3c..859e06b 100644 --- a/lib/Net/Riak/Role/REST/Object.pm +++ b/lib/Net/Riak/Role/REST/Object.pm @@ -1,6 +1,7 @@ package Net::Riak::Role::REST::Object; use Moose::Role; +use Data::Dumper; use JSON; sub store_object { @@ -32,13 +33,20 @@ sub store_object { $request->header('link' => $self->_links_to_header($object)); } + if ( $object->i2indexes) { + + foreach (keys %{$object->i2indexes}) { + $request->header(':x-riak-index-' . lc($_) => $object->i2indexes->{$_}); + } + } + if (ref $object->data && $object->content_type eq 'application/json') { $request->content(JSON::encode_json($object->data)); } else { $request->content($object->data); } - + my $response = $self->send_request($request); $self->populate_object($object, $response, [200, 201, 204, 300]); return $object; @@ -75,7 +83,8 @@ sub populate_object { $obj->exists(0); return if (!$http_response); - + + my $status = $http_response->code; $obj->data($http_response->content) @@ -91,6 +100,13 @@ sub populate_object { . (join(', ', @$expected)) . ", received: ".$http_response->status_line } + + $HTTP::Headers::TRANSLATE_UNDERSCORE = 0; + foreach ( $http_response->header_field_names ) { + next unless /^X-Riak-Index-(.+_bin)/; + $obj->i2index({ lc($1) => $http_response->header($_) }) + } + $HTTP::Headers::TRANSLATE_UNDERSCORE = 1; if ($status == 404) { $obj->clear; diff --git a/lib/Net/Riak/Search.pm b/lib/Net/Riak/Search.pm index ee2ed57..646d4d3 100644 --- a/lib/Net/Riak/Search.pm +++ b/lib/Net/Riak/Search.pm @@ -33,6 +33,13 @@ sub setup_indexing { $bucket->delete_object($key, 3); # optional w val + # Secondary index setup + my $obj3 = $bucket->new_object('foo3', {...}); + $obj3->i2index({ myindex_bin => 'myvalue' }); + $obj3->store; + + my @keys = $client->i2search(bucket => 'foo', index => 'myindex_bin', key => 'myvalue' ); + =head1 DESCRIPTION L allows you to enable indexing documents for a given bucket and querying/searching the index. @@ -80,6 +87,15 @@ is the default index you want to query, if no index is provided you have to add is the number of documents you want to be returned in the response +=item i2index + +add secondary index to object + +=item i2search + +Find keys via secondary index. + + =back More parameters are available, just check at L -- cgit 1.4.1 From 1b442767f0bc92b98c3a398dde02dae6212ecd1c Mon Sep 17 00:00:00 2001 From: Mainframe2008 Date: Tue, 26 Feb 2013 08:44:28 +0100 Subject: *Added secondary index support using method names from the riak python client. * Added tests for secondary indexes * Added documentation --- lib/Net/Riak.pm | 16 ++++++++++--- lib/Net/Riak/Object.pm | 51 +++++++++++++++++++++++++++++----------- lib/Net/Riak/Role/REST/Object.pm | 4 ++-- lib/Net/Riak/Role/REST/Search.pm | 28 +++++++++++++--------- lib/Net/Riak/Search.pm | 12 ++++++---- t/25-2index.t | 17 ++++++++++++++ 6 files changed, 94 insertions(+), 34 deletions(-) create mode 100644 t/25-2index.t (limited to 'lib/Net/Riak/Role') diff --git a/lib/Net/Riak.pm b/lib/Net/Riak.pm index 4f2bfe5..1fd23a6 100644 --- a/lib/Net/Riak.pm +++ b/lib/Net/Riak.pm @@ -14,7 +14,7 @@ has client => ( is => 'rw', isa => Client_T, required => 1, - handles => [qw/is_alive all_buckets server_info stats search i2search setup_indexing/] + handles => [qw/is_alive all_buckets server_info stats search index setup_indexing/] ); sub BUILDARGS { @@ -68,10 +68,20 @@ sub bucket { # Secondary index setup (REST interface) my $obj3 = $bucket->new_object('foo3', {...}); - $obj3->i2index({ myindex_bin => 'myvalue' }); + $obj3->add_index('myindex_bin','myvalue' ); + $obj3->add_index('number_int', 1001); $obj3->store; - my @keys = $client->i2search(bucket => 'foo', index => 'myindex_bin', key => 'myvalue' ); + # Get all keys for a specific index/value pair + my @keys = $client->index('mybucket', 'myindex_bin', 'myvalue' ); + + # Get all keys for a range of index value pairs + my @keys = $client->index('mybucket', 'number_int', 500, 1500); + + # Removing a secondary index (REST interface) + my $new_obj = $bucket->get('foo3'); + $new_obj->remove_index('number_int', 1001); + $new_obj->store; =head1 DESCRIPTION diff --git a/lib/Net/Riak/Object.pm b/lib/Net/Riak/Object.pm index 8e48dcb..aa8fbcd 100644 --- a/lib/Net/Riak/Object.pm +++ b/lib/Net/Riak/Object.pm @@ -73,31 +73,54 @@ sub store { $self->client->store_object($w, $dw, $self); } -sub i2index { - my($self, $args) = @_; +sub add_index { + my($self, $index, $data) = @_; - if ( defined($args) ) { - my %args = %{$args}; + if ( defined($index) && defined($data) ) { my $ref = undef; if ( defined($self->i2indexes) ) { $ref = $self->i2indexes; } - foreach my $i (keys %args) + + if ( length($index) > 4 && $index =~ /^.+_bin$/ && length($data) > 0 ) { + $ref->{$index} = $data; - #$i = lc($i); - print $i,"\n"; - if ( defined($args{$i}) && length($args{$i}) > 0 ) - { - $ref->{$i} = $args{$i}; - - } else { - delete $ref->{$i}; - } + } + if ( length($index) > 4 && $index =~ /^.+_int$/ && $data =~ /^\d+$/ ) + { + $ref->{$index} = $data; } $self->i2indexes($ref); } $self->i2indexes; } +sub remove_index { + my($self, $index, $data) = @_; + if ( defined($index) && defined($data) ) { + if ( defined($self->i2indexes) ) { + my $ref = $self->i2indexes; + + if ( $index =~ /^.+_bin$/ ) { + if ( defined($ref->{$index}) && $ref->{$index} eq $data ) + { + + delete(${$ref}{$index}); + } + $self->i2indexes($ref); + } + if ( $index =~ /^.+_int$/ ) { + if ( defined($ref->{$index}) && $ref->{$index} == $data ) + { + print "Deleting $index\n"; + delete(${$ref}{$index}); + } + $self->i2indexes($ref); + } + print Dumper($ref),"\n"; + } + } +} + sub status { my ($self) = @_; warn "DEPRECATED: status method will be removed in the 0.17 release, please use ->client->status."; diff --git a/lib/Net/Riak/Role/REST/Object.pm b/lib/Net/Riak/Role/REST/Object.pm index 859e06b..545e4e0 100644 --- a/lib/Net/Riak/Role/REST/Object.pm +++ b/lib/Net/Riak/Role/REST/Object.pm @@ -103,8 +103,8 @@ sub populate_object { $HTTP::Headers::TRANSLATE_UNDERSCORE = 0; foreach ( $http_response->header_field_names ) { - next unless /^X-Riak-Index-(.+_bin)/; - $obj->i2index({ lc($1) => $http_response->header($_) }) + next unless /^X-Riak-Index-(.+_bin)$/ || /^X-Riak-Index-(.+_int)$/; + $obj->add_index(lc($1), $http_response->header($_) ) } $HTTP::Headers::TRANSLATE_UNDERSCORE = 1; diff --git a/lib/Net/Riak/Role/REST/Search.pm b/lib/Net/Riak/Role/REST/Search.pm index 7e74af5..f813578 100644 --- a/lib/Net/Riak/Role/REST/Search.pm +++ b/lib/Net/Riak/Role/REST/Search.pm @@ -74,21 +74,27 @@ sub setup_indexing { JSON::decode_json($http_response->content); } -sub i2search { - my $self = shift; - my %params = @_; +sub index { + my ($self, $bucket,$index,$first, $last) = @_; + my $request; + my @req = (); my $org_prefix = $self->prefix; - - $request = $self->new_request('GET', [ + if ( defined($bucket) && defined($index) && defined($first) ) + { + @req = ( 'buckets', - $params{bucket}, - 'index', - $params{index}, - $params{key} - ] - ); + $bucket, + 'index', + $index, + $first + ); + + if ( defined($last) ) { push(@req, $last); } + } + + $request = $self->new_request('GET', [ @req ] ); my $http_response = $self->send_request($request); JSON::decode_json($http_response->content)->{keys}; diff --git a/lib/Net/Riak/Search.pm b/lib/Net/Riak/Search.pm index 646d4d3..368b7e7 100644 --- a/lib/Net/Riak/Search.pm +++ b/lib/Net/Riak/Search.pm @@ -35,10 +35,10 @@ sub setup_indexing { # Secondary index setup my $obj3 = $bucket->new_object('foo3', {...}); - $obj3->i2index({ myindex_bin => 'myvalue' }); + $obj3->add_index('index', 'first'); $obj3->store; - my @keys = $client->i2search(bucket => 'foo', index => 'myindex_bin', key => 'myvalue' ); + my @keys = $client->index('bucket', 'myindex_bin', 'first_value' [, 'last_value'] ); =head1 DESCRIPTION @@ -87,11 +87,15 @@ is the default index you want to query, if no index is provided you have to add is the number of documents you want to be returned in the response -=item i2index +=item add_index add secondary index to object -=item i2search += item remove_index + +remove secondary index from object + +=item index Find keys via secondary index. diff --git a/t/25-2index.t b/t/25-2index.t new file mode 100644 index 0000000..c6d420c --- /dev/null +++ b/t/25-2index.t @@ -0,0 +1,17 @@ +use lib 't/lib'; +use Test::More; +use Test::Riak; + +test_riak_rest { + my ($client, $bucket_name) = @_; + my $content = { field => "2index" }; + ok my $bucket = $client->bucket($bucket_name), 'got bucket test'; + ok my $obj = $bucket->new_object('2ikey', $content), + 'created a new riak object for seconday index'; + ok $obj->add_index('myindex_bin', 'value'), 'Secondary index created'; + + ok $obj->store, 'Object with secondary index stored'; + ok my $newobj->get('2ikey'), 'Object with secondary index retrieved'; + ok $newobj->remove_index('myindex_bin', 'value'), 'Secondary index removed'; + ok $newobj->store, "Object without secondary index saved"; +} \ No newline at end of file -- cgit 1.4.1