Skip to content

Instantly share code, notes, and snippets.

@marcusramberg
Created October 30, 2008 12:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marcusramberg/20983 to your computer and use it in GitHub Desktop.
Save marcusramberg/20983 to your computer and use it in GitHub Desktop.
package MojoMojo::Model::Search;
use strict;
use base 'Catalyst::Model';
use KinoSearch::InvIndexer;
use KinoSearch::Searcher;
use KinoSearch::Analysis::PolyAnalyzer;
use KinoSearch::Index::Term;
use KinoSearch::Search::Query;
use KinoSearch::QueryParser::QueryParser;
use Data::Dumper;
__PACKAGE__->config->{index} ||= MojoMojo->path_to('/index');
my $invindexer;
my $analyzer
= KinoSearch::Analysis::PolyAnalyzer->new( language => 'en');
sub indexer {
my $self=shift;
unless ($invindexer) {
$invindexer ||= KinoSearch::InvIndexer->new(
invindex => __PACKAGE__->config->{index},
create => ( -f __PACKAGE__->config->{index}.'/segments' ? 0 : 1 ),
analyzer => $analyzer,
);
$invindexer->spec_field(name=>'path');
$invindexer->spec_field(name=>'text');
$invindexer->spec_field(name=>'author');
$invindexer->spec_field(name=>'date');
$invindexer->spec_field(name=>'tags');
}
return $invindexer;
}
my $searcher;
sub searcher {
my $self=shift;
$searcher ||= KinoSearch::Searcher->new(
invindex => __PACKAGE__->config->{index},
analyzer => $analyzer,
);
return $searcher;
}
=item prepare_search_index
Create a new search index from all pages in the database.
Will do nothing if the index already exists.
=cut
sub prepare_search_index {
my $self = shift;
my $index = $self->indexer;
# is the root page already indexed?
return if ( $index->is_indexed('/') );
MojoMojo->log->info("Initializing search index...")
if MojoMojo->debug;
# loop through all latest-version pages
my $count = 0;
my $it = MojoMojo->model('DB::Page')->search;
while ( my $page = $it->next ) {
$page->set_paths($page);
$self->index_page($page);
$count++;
}
MojoMojo->log->info("Indexed $count pages") if MojoMojo->debug;
}
=item index_page <page>
Create/update the search index with data from a MojoMojo page.
=cut
# updates the search index when page data changes
sub index_page {
my ( $self, $page ) = @_;
my $index = $self->indexer;
return unless ( $page && $page->content );
my $content = $page->content;
my $key = $page->path;
my $text = $content->body;
$text .= " " . $content->abstract if ( $content->abstract );
$text .= " " . $content->comments if ( $content->comments );
# translate the path into plain text so we can use it in the search query later
my $fixed_path = $key;
$fixed_path =~ s{/}{X}g;
my $term = KinoSearch::Index::Term->new(path => $fixed_path );
$index->delete_docs_by_term( $term );
my $doc=$index->new_doc();
$doc->set_value(author => $content->creator->login);
$doc->set_value(path => $fixed_path);
$doc->set_value(date => ( $content->created ) ? $content->created->ymd : '');
$doc->set_value(tags => join( ' ', map { $_->tag } $page->tags ));
$doc->set_value(text => $text);
$index->add_doc($doc);
$index->finish(optimize=>1);
undef $invindexer;
}
sub search {
my ($self,$q) = @_;
my $qp=KinoSearch::QueryParser::QueryParser->new(analyzer=>$analyzer,fields=>['text','tags']);
my $query=$qp->parse($q);
my $hits=$self->searcher->search( query=> $query );
return $hits;
}
1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment