3 |
use strict; |
use strict; |
4 |
use warnings; |
use warnings; |
5 |
use base qw( Class::Accessor ); |
use base qw( Class::Accessor ); |
6 |
Grep::Search->mk_accessors( qw( invindexer create index_path ) ); |
Grep::Search->mk_accessors( qw( invindexer create index_path hits ) ); |
7 |
|
|
8 |
use Data::Dump qw/dump/; |
use Data::Dump qw/dump/; |
9 |
use KinoSearch::InvIndexer; |
use KinoSearch::InvIndexer; |
22 |
|
|
23 |
my $search = Grep::Search->new(); |
my $search = Grep::Search->new(); |
24 |
|
|
25 |
|
my $search = Grep::Search->new( create => 1 ); |
26 |
|
|
27 |
|
=head2 invindexer |
28 |
|
|
29 |
|
Accessor to call any method defined on L<KinoSearch::InvIndexer> |
30 |
|
|
31 |
|
$search->invindexer->delete_by_term( 'id', 42 ); |
32 |
|
|
33 |
=cut |
=cut |
34 |
|
|
35 |
sub log { Jifty->web->log } |
sub log { Jifty->web->log } |
42 |
|
|
43 |
$self->index_path( $index_path ); |
$self->index_path( $index_path ); |
44 |
|
|
45 |
if (! -e "$index_path") { |
if ( ! -e "$index_path" || $self->create ) { |
46 |
$self->log->debug("Creating new index $index_path"); |
$self->log->debug("Creating new index $index_path"); |
47 |
$self->invindexer( KinoSearch::InvIndexer->new( invindex => Grep::Search::Schema->clobber( $index_path ) ) ); |
$self->invindexer( KinoSearch::InvIndexer->new( invindex => Grep::Search::Schema->clobber( $index_path ) ) ); |
48 |
} else { |
} else { |
121 |
$self->invindexer->add_doc( $doc ); |
$self->invindexer->add_doc( $doc ); |
122 |
|
|
123 |
$self->log->debug("added ", $i->id, " for user $uid to index"); |
$self->log->debug("added ", $i->id, " for user $uid to index"); |
124 |
|
|
125 |
|
return 1; |
126 |
} |
} |
127 |
|
|
128 |
=head2 collection |
=head2 collection |
129 |
|
|
130 |
|
Return C<Grep::Model::ItemCollection> which is result of C<search query> |
131 |
|
|
132 |
my $ItemCollection = $search->collection( 'search query' ); |
my $ItemCollection = $search->collection( 'search query' ); |
133 |
|
|
134 |
|
=head2 hits |
135 |
|
|
136 |
|
Return number of results from last C<collection> call |
137 |
|
|
138 |
|
my $num_results = $search->hits; |
139 |
|
|
140 |
=cut |
=cut |
141 |
|
|
142 |
sub collection { |
sub collection { |
148 |
invindex => Grep::Search::Schema->open( $self->index_path ), ); |
invindex => Grep::Search::Schema->open( $self->index_path ), ); |
149 |
$self->log->debug("$searcher created"); |
$self->log->debug("$searcher created"); |
150 |
|
|
151 |
my $full_q = "($q) AND _owner_id:" . Jifty->web->current_user->id; |
my $full_q = "($q)"; |
152 |
|
|
153 |
|
my $uid = Jifty->web->current_user->id; |
154 |
|
$full_q .= ' AND _owner_id:' . $uid if (defined $uid); |
155 |
|
|
156 |
$self->log->debug("searching for '$q' using $full_q"); |
$self->log->debug("searching for '$q' using $full_q"); |
157 |
|
|
158 |
|
my $query_parser = KinoSearch::QueryParser->new( |
159 |
|
schema => Grep::Search::Schema->new, |
160 |
|
fields => [ qw/ title link content summary category author / ], |
161 |
|
); |
162 |
|
$query_parser->set_heed_colons(1); # enable field:value AND/OR/NOT syntax |
163 |
|
my $query = $query_parser->parse( $full_q ); |
164 |
my $hits = $searcher->search( |
my $hits = $searcher->search( |
165 |
query => $full_q, |
query => $query, |
166 |
# offset => $offset, |
# offset => $offset, |
167 |
# num_wanted => $hits_per_page, |
# num_wanted => $hits_per_page, |
168 |
); |
); |
169 |
|
|
170 |
my $num_hits = $hits->total_hits; |
$self->hits( $hits->total_hits ); |
171 |
|
|
172 |
$self->log->debug("found $num_hits results"); |
$self->log->debug("found ", $self->hits, " results"); |
173 |
|
|
174 |
my $collection = Grep::Model::ItemCollection->new(); |
my $collection = Grep::Model::ItemCollection->new(); |
175 |
|
|
182 |
my $title = $hit->{title}; |
my $title = $hit->{title}; |
183 |
my $id = $hit->{id}; |
my $id = $hit->{id}; |
184 |
|
|
185 |
$self->log->debug("result $i $score $title"); |
$self->log->debug("result $i [$id] $title $score"); |
186 |
|
|
187 |
my $item = Grep::Model::Item->new(); |
my $item = Grep::Model::Item->new(); |
188 |
my ($ok,$msg) = $item->load_by_cols( id => $id ); |
my ($ok,$msg) = $item->load_by_cols( id => $id ); |
217 |
|
|
218 |
undef $self; |
undef $self; |
219 |
|
|
220 |
return; |
return 1; |
221 |
} |
} |
222 |
|
|
|
=cut |
|
|
|
|
223 |
=head2 snippet |
=head2 snippet |
224 |
|
|
225 |
my $short = $self->snippet( 50, $text ); |
my $short = $self->snippet( 50, $text ); |
244 |
package Grep::Search::KeywordField; |
package Grep::Search::KeywordField; |
245 |
use base qw( KinoSearch::Schema::FieldSpec ); |
use base qw( KinoSearch::Schema::FieldSpec ); |
246 |
sub analyzed { 0 } |
sub analyzed { 0 } |
247 |
|
#sub indexed { 1 } |
248 |
|
#sub stored { 1 } |
249 |
|
sub vectorized { 0 } |
250 |
|
|
251 |
package Grep::Search::Schema; |
package Grep::Search::Schema; |
252 |
|
|
253 |
=head1 NAME |
=head1 NAME |
254 |
|
|
255 |
Grep::Search::Schema - data definition |
Grep::Search::Schema - schema definition for full-text search |
256 |
|
|
257 |
=cut |
=cut |
258 |
|
|
259 |
use base 'KinoSearch::Schema'; |
use base 'KinoSearch::Schema'; |
260 |
use KinoSearch::Analysis::PolyAnalyzer; |
use KinoSearch::Analysis::PolyAnalyzer; |
261 |
|
|
262 |
our %FIELDS = ( |
our %fields = ( |
263 |
id => 'Grep::Search::KeywordField', |
id => 'Grep::Search::KeywordField', |
264 |
|
|
265 |
in_feed_id => 'Grep::Search::KeywordField', |
in_feed_id => 'Grep::Search::KeywordField', |