package Metadata::ByInode::Search; use strict; use warnings; our $VERSION = sprintf "%d.%02d", q$Revision: 1.11 $ =~ /(\d+)/g; #returns boolean, did a search complete? sub _sran { my $self= shift; $self->{_search} or return 0; return 1; } sub results_count { my $self = shift; $self->_sran or return; return $self->{_search}->{count}; } sub search_results { my $self = shift; $self->_sran or return; $self->results_count or return []; # return empty if none found unless ( defined $self->{_search}->{results_array}) { for (keys %{$self->{_search}->{data}} ){ my $inode = $_; my $hash = $self->{_search}->{data}->{$inode}; $hash->{inode} = $inode; push @{$self->{_search}->{results_array}},$hash; } } return $self->{_search}->{results_array}; } sub search { # multiple key lookup and ranked my $self = shift; my $arg = shift; ref $arg eq 'HASH' or croak('missing arg to search'); # keys in search args? keys %{$arg} or croak('no arguments, must be hash ref with args and vals'); $self->_search_reset; my $argcount = keys %{$arg}; ### $argcount my $select= { 'like' => $self->dbh->prepare("SELECT * FROM metadata WHERE mkey=? and mvalue LIKE ?"), 'exact' => $self->dbh->prepare("SELECT * FROM metadata WHERE mkey=? and mvalue=?"), }; my $sk = 'like'; #default my $RESULT = {}; for ( keys %{$arg} ){ my ($key,$value)= ($_,undef); if ($key=~s/:exact$//){ # EXACT, so they can override the like $value = $arg->{$_}; $sk= 'exact'; } else { # LIKE $key=~s/:like$//; # just in case $value = "%".$arg->{$_}."%"; $sk ='like' } $select->{$sk}->execute($key,$value) or warn("cannot search? $DBI::errstr"); while ( my $row = $select->{$sk}->fetch ){ $RESULT->{$row->[0]}->{_hit}++; } } # just leave the result whose count matches num of args? # instead should order them to the back.. ? my $count = 0; for (keys %{$RESULT}){ if( $RESULT->{$_}->{_hit} < $argcount ){ delete $RESULT->{$_}; next; } $RESULT->{$_} = $self->get_all($_); $count++; } $self->{_search}->{count} = $count; $self->{_search}->{data} = $RESULT; return $RESULT; } sub _search_reset { my $self = shift; $self->{_search} = undef; return 1; } 1; __END__ =pod =head1 NAME Metadata::ByInode::Search =head1 DESCRIPTION this is not meant to be used directly. this is part of Metadata::ByInode =head1 search() Parameter is a hash ref with metadata keys and values you want to look up by. Imagine you want to search for all metadata for a file whose absolute path you know. my $RESULT = $mbi->search ({ filename => 'pm', abs_loc => '/home/leo/devel/Metadata-ByInode/lib' },); Returns hash of hashes. Key is inode. search() is NOT an exact match. it is a LIKE function by default. If you want some keys to be exact then you must defined the key as: my $RESULT = $mbi->search ({ filename => 'pm', 'abs_loc:exact' => '/home/leo/devel/Metadata-ByInode/lib' },); This would make the abs_loc be exactly '/home/leo/devel/Metadata-ByInode/lib', and the filename would match '*pm*'. Notice that this is the same thing: my $RESULT = $mbi->search ({ 'filename:like' => 'pm', 'abs_loc:exact' => '/home/leo/devel/Metadata-ByInode/lib' },); example output: $RESULT: { '7496560' => { abs_loc => '/home/leo/devel/Metadata-ByInode/lib/Metadata', filename => 'ByInode.pm', ondisk => '1164911227' }, '7725851' => { abs_loc => '/home/leo/devel/Metadata-ByInode/lib/Metadata/ByInode', filename => 'Search.pm', ondisk => '1164911227' }, '7725852' => { abs_loc => '/home/leo/devel/Metadata-ByInode/lib/Metadata/ByInode', filename => 'Index.pm', ondisk => '1164911227' } } =head1 search_results() Return the search results in an array ref, each array ref has an anon hash with file details as: $search_results = [ { abs_loc => '/tmp', filename => 'file1', ondisk => 1231231231, inode => 234, abs_path => '...' }, { abs_loc => '/tmp/dir', filename => 'file2', ondisk => 1231231231, inode => 143, abs_path => '...' }, ]; If no search results are present beacuse nothing was found, returns [] anon array ref, empty. If no search was run, returns undef. =head1 results_count() If a search was run, how many results are there, returns number. if nothing was found, returns 0 Returns undef if no search was run. =head1 SEE ALSO L<Metadata::ByInode> and L<Metadata::ByInode::Indexer> =head1 AUTHOR Leo Charre <leo@leocharre.com> =cut