3 use Time::HiRes qw(time);
4 use Constants qw(@SEARCH_EXCLUDE @SEARCH_INCLUDE);
7 our $VERSION = "1.006";
16 file_displayName => 2,
25 my ($class, %opts) = @_;
27 my $cfg = BSE::Cfg->single;
28 unless ($opts{scores}) {
29 my $scores = { %default_scores };
30 for my $field (keys %$scores) {
31 $scores->{$field} = $cfg->entry("search index scores", $field, $scores->{$field});
33 $opts{scores} = $scores;
36 $opts{max_level} ||= $cfg->entry("search", "level", $Constants::SEARCH_LEVEL);
38 return bless \%opts, $class;
44 unless ($self->{indexer}) {
45 my $cfg = BSE::Cfg->single;
46 my $indexer_class = $cfg->entry('search', 'indexer', 'BSE::Index::BSE');
47 (my $indexer_file = $indexer_class . ".pm") =~ s!::!/!g;
48 require $indexer_file;
50 $self->{indexer} = $indexer_class->new
53 scores => $self->{scores},
54 verbose => $self->{verbose},
58 return $self->{indexer};
64 my $indexer = $self->indexer;
66 $self->vnote("s1::Starting index");
67 $indexer->start_index();
68 $self->vnote("s2::Starting article scan");
70 $self->vnote("f2::Populating search index");
71 $indexer->end_index();
72 $self->vnote("f1::Indexing complete");
75 $self->_error("Indexing error: $@");
86 @dont_search{@SEARCH_EXCLUDE} = @SEARCH_EXCLUDE;
87 @do_search{@SEARCH_INCLUDE} = @SEARCH_INCLUDE;
88 $self->vnote("s::Loading article ids");
89 my @ids = BSE::TB::Articles->allids;
91 $self->vnote("c:$count:$count articles to index");
92 my $cfg = BSE::Cfg->single;
93 my $indexer = $self->indexer;
95 INDEX: for my $id (@ids) {
99 my $article = BSE::TB::Articles->getByPkey($id);
100 next unless $article;
101 next unless $article->should_index;
102 my $section = $article->section;
103 my $id = $article->{id};
104 my $indexas = $article->indexed_as;
105 my $sectionid = $section->{id};
106 eval "use $article->{generator}";
108 my $gen = $article->{generator}->new(top=>$article, cfg=>$cfg);
109 next unless $gen->visible($article) or $do_search{$sectionid};
111 next if $dont_search{$sectionid};
113 $article = $gen->get_real_article($article);
116 $self->error("$id:Full article for $id not found");
120 $self->vnote("i:$id:Indexing '$article->{title}'");
123 my $scores = $self->{scores};
124 for my $field (sort { $scores->{$b} <=> $scores->{$a} } keys %$scores) {
126 next unless $self->{scores}{$field};
129 if (exists $article->{$field}) {
130 $text = $article->{$field};
133 if ($field =~ /^file_(.*)/) {
135 @files = $article->files unless $got_files++;
136 $text = join "\n", map $_->{$file_field}, @files;
139 #next if $text =~ m!^\<html\>!i; # I don't know how to do this (yet)
140 if ($field eq 'body') {
141 $gen->remove_block("BSE::TB::Articles", [], \$text);
142 $text =~ s/[abi]\[([^\]]+)\]/$1/g;
145 next unless defined $text;
147 $fields{$field} = $text;
149 $indexer->process_article($article, $section, $indexas->id, \%fields);
151 $self->vnote("f::Article scan complete");
155 my ($self, @msg) = @_;
157 $self->_error($self->_time_passed, ":e:", @msg);
161 my ($self, @error) = @_;
163 if ($self->{error}) {
164 $self->{error}->(@error);
174 return sprintf("%.3f", time() - $self->{start});
178 my ($self, @msg) = @_;
180 $self->_note($self->_time_passed, ":", @msg);
184 my ($self, @msg) = @_;
187 $self->{note}->(@msg);