Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Moritz Onken
committed
May 29, 2009
1 parent
6ceb8be
commit c362627
Showing
5 changed files
with
256 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package DBIx::Class::ResultSet::PhoneticSearch; | ||
|
||
use base 'DBIx::Class::ResultSet'; | ||
|
||
use strict; | ||
use warnings; | ||
|
||
use Carp; | ||
|
||
sub search_phonetic { | ||
my ( $self, $search, $attributes ) = @_; | ||
|
||
$attributes ||= {}; | ||
|
||
my $source = $self->result_source; | ||
|
||
my @search = | ||
ref $search eq 'ARRAY' ? @{$search} | ||
: ref $search eq 'HASH' ? %{$search} | ||
: croak 'search_phonetic takes an arrayref or a hashref'; | ||
|
||
my $type = ref $search eq 'ARRAY' ? '-or' : '-and'; | ||
|
||
my $query = []; | ||
|
||
while ( my $column = shift @search ) { | ||
my $value = shift @search; | ||
$column =~ s/^(.*?\.)?(.*)$/$2/; | ||
my $prefix = $1 || q{}; | ||
my $info = $source->column_info($column); | ||
croak qq(Column '$column' is not a phonetic column) | ||
unless ( my $config = $info->{phonetic_search} ); | ||
|
||
my $class = 'Text::Phonetic::' . $config->{algorithm}; | ||
my $column = $column . '_phonetic_' . lc( $config->{algorithm} ); | ||
Class::Load::load_class($class); | ||
my $encoded_value = $class->new->encode($value); | ||
|
||
push(@{$query}, { "$prefix$column" => $encoded_value}); | ||
|
||
} | ||
|
||
return $self->search( { $type => $query }, $attributes ); | ||
} | ||
|
||
sub update_phonetic_columns { | ||
my ($self) = @_; | ||
my $i = 0; | ||
my $source = $self->result_source; | ||
foreach my $column ( $source->columns ) { | ||
$i += $self->update_phonetic_column($column); | ||
} | ||
return $i; | ||
} | ||
|
||
sub update_phonetic_column { | ||
my ( $self, $column ) = @_; | ||
my $source = $self->result_source; | ||
my $config = $source->column_info($column)->{phonetic_search}; | ||
my $i; | ||
return 0 unless ($config); | ||
my $class = 'Text::Phonetic::' . $config->{algorithm}; | ||
my $phonetic_column = $column . '_phonetic_' . lc( $config->{algorithm} ); | ||
Class::Load::load_class($class); | ||
my $rs = $self->search( { $column => { '!=' => undef } } ); | ||
|
||
while ( my $row = $rs->next ) { | ||
$row->update( | ||
{ $phonetic_column => $class->new->encode( $row->$column ) } ); | ||
$i++; | ||
} | ||
return $i; | ||
} | ||
|
||
1; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
{ | ||
package | ||
Schema::Item; | ||
|
||
use base 'DBIx::Class'; | ||
|
||
__PACKAGE__->load_components(qw(PhoneticSearch Core)); | ||
|
||
__PACKAGE__->table('item'); | ||
|
||
__PACKAGE__->add_columns( | ||
id => { data_type => 'integer', auto_increment => 1, }, | ||
name1 => { data_type => 'character varying', phonetic_search => 1 }, | ||
name2 => { data_type => 'character varying', is_nullable => 1, phonetic_search => { algorithm => 'Koeln' } } | ||
|
||
); | ||
|
||
__PACKAGE__->set_primary_key('id'); | ||
|
||
__PACKAGE__->resultset_class('DBIx::Class::ResultSet::PhoneticSearch'); | ||
|
||
} | ||
|
||
|
||
{ | ||
package | ||
Schema; | ||
|
||
use base 'DBIx::Class::Schema'; | ||
|
||
__PACKAGE__->load_classes('Item'); | ||
|
||
sub connect { | ||
my $class = shift; | ||
my $schema = $class->next::method('dbi:SQLite::memory:'); | ||
$schema->deploy; | ||
return $schema; | ||
} | ||
|
||
} | ||
|
||
1; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
use Test::More tests => 13; | ||
|
||
use strict; | ||
use warnings; | ||
|
||
use lib qw(t/lib); | ||
use Schema; | ||
|
||
my $s = Schema->connect; | ||
|
||
my $rs = $s->resultset('Item'); | ||
|
||
eval { $rs->search_phonetic({ foobar => 'xyz' }) }; | ||
|
||
ok($@, 'error on unknown columns: '.$@); | ||
|
||
eval { $rs->search_phonetic({ id => 'xyz' }) }; | ||
|
||
ok($@, 'error on non-phonetic columns: '.$@); | ||
|
||
$rs->create({name1 => 'Meyer', name2 => 'Peter'}); | ||
|
||
$rs->create({name1 => 'Schmidt', name2 => 'Moritz'}); | ||
|
||
my @found = $rs->search_phonetic({ name1 => 'Meyer', name2 => 'Peter'}); | ||
|
||
is(@found, 1, 'one result found'); | ||
|
||
@found = $rs->search_phonetic({ name1 => 'Meier', name2 => 'Peter'}); | ||
|
||
is(@found, 1, 'one result found'); | ||
|
||
@found = $rs->search_phonetic({ 'me.name1' => 'Meier', 'me.name2' => 'Peter'}); | ||
|
||
is(@found, 1, 'one result found with prefix'); | ||
|
||
@found = $rs->search_phonetic([ name1 => 'Meier', name1 => 'Meyer']); | ||
|
||
is(@found, 1, 'one result found in OR search'); | ||
|
||
@found = $rs->search_phonetic([ name1 => 'Meier', name1 => 'Foo']); | ||
|
||
is(@found, 1, 'zero results found in OR search'); | ||
|
||
@found = $rs->search_phonetic([ name2 => 'Moriz']); | ||
|
||
is(@found, 1, 'moriz found instead of moritz'); | ||
|
||
is($rs->update_phonetic_columns, 4, 'updates 4 rows'); | ||
|
||
is($rs->update_phonetic_column('name1'), 2, 'updates 2 rows'); | ||
|
||
is($rs->result_source->column_info('name1')->{phonetic_search}->{algorithm}, 'Phonix', 'algorithm is set'); | ||
|
||
is($rs->result_source->column_info('name2')->{phonetic_search}->{algorithm}, 'Koeln', 'algorithm is set'); | ||
|
||
$rs->create({name1 => 'Schmidt', name2 => 'Moriz'}); | ||
|
||
$rs->create({name1 => 'Schmidt', name2 => 'Moriiz'}); | ||
|
||
@found = $rs->search_phonetic({ name2 => 'Moriiz'}, { order_by => { -desc => \[ 'name2 LIKE ?', 'Moriiz' ] } }); | ||
|
||
is($found[0]->name2, "Moriiz", 'sorting for exact match'); | ||
|
||
|
||
|
||
|
||
|
||
|