Bug 12478: fix errors from rebase and new upstream version
[koha.git] / misc / search_tools / rebuild_elastic_search.pl
1 #!/usr/bin/perl
2
3 # This inserts records from a Koha database into elastic search
4
5 # Copyright 2014 Catalyst IT
6 #
7 # This file is part of Koha.
8 #
9 # Koha is free software; you can redistribute it and/or modify it under the
10 # terms of the GNU General Public License as published by the Free Software
11 # Foundation; either version 3 of the License, or (at your option) any later
12 # version.
13 #
14 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
15 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License along
19 # with Koha; if not, write to the Free Software Foundation, Inc.,
20 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
22 =head1 NAME
23
24 rebuild_elastic_search.pl - inserts records from a Koha database into Elasticsearch
25
26 =head1 SYNOPSIS
27
28 B<rebuild_elastic_search.pl>
29 [B<-c|--commit>=C<count>]
30 [B<-v|--verbose>]
31 [B<-h|--help>]
32 [B<--man>]
33
34 =head1 DESCRIPTION
35
36 Inserts records from a Koha database into Elasticsearch.
37
38 =head1 OPTIONS
39
40 =over
41
42 =item B<-c|--commit>=C<count>
43
44 Specify how many records will be batched up before they're added to Elasticsearch.
45 Higher should be faster, but will cause more RAM usage. Default is 5000.
46
47 =item B<-d|--delete>
48
49 Delete the index and recreate it before indexing.
50
51 =item B<-a|--authorities>
52
53 Index the authorities only. Combining this with B<-b> is the same as
54 specifying neither and so both get indexed.
55
56 =item B<-b|--biblios>
57
58 Index the biblios only. Combining this with B<-a> is the same as
59 specifying neither and so both get indexed.
60
61 =item B<-bn|--bnumber>
62
63 Only index the supplied biblionumber, mostly for testing purposes. May be
64 repeated. This also applies to authorities via authid, so if you're using it,
65 you probably only want to do one or the other at a time.
66
67 =item B<-v|--verbose>
68
69 By default, this program only emits warnings and errors. This makes it talk
70 more. Add more to make it even more wordy, in particular when debugging.
71
72 =item B<-h|--help>
73
74 Help!
75
76 =item B<--man>
77
78 Full documentation.
79
80 =back
81
82 =cut
83
84 use autodie;
85 use Getopt::Long;
86 use Koha::Authority;
87 use Koha::BiblioUtils;
88 use Koha::ElasticSearch::Indexer;
89 use MARC::Field;
90 use MARC::Record;
91 use Modern::Perl;
92 use Pod::Usage;
93
94 use Data::Dumper; # TODO remove
95
96 my $verbose = 0;
97 my $commit = 5000;
98 my ($delete, $help, $man);
99 my ($index_biblios, $index_authorities);
100 my (@biblionumbers);
101
102 GetOptions(
103     'c|commit=i'       => \$commit,
104     'd|delete'         => \$delete,
105     'a|authorities' => \$index_authorities,
106     'b|biblios' => \$index_biblios,
107     'bn|bnumber=i' => \@biblionumbers,
108     'v|verbose+'       => \$verbose,
109     'h|help'           => \$help,
110     'man'              => \$man,
111 );
112
113 # Default is to do both
114 unless ($index_authorities || $index_biblios) {
115     $index_authorities = $index_biblios = 1;
116 }
117
118 pod2usage(1) if $help;
119 pod2usage( -exitstatus => 0, -verbose => 2 ) if $man;
120
121 my $next;
122 if ($index_biblios) {
123     _log(1, "Indexing biblios\n");
124     if (@biblionumbers) {
125         $next = sub {
126             my $r = shift @biblionumbers;
127             return () unless defined $r;
128             return ($r, Koha::BiblioUtils->get_from_biblionumber($r, item_data => 1 ));
129         };
130     } else {
131         my $records = Koha::BiblioUtils->get_all_biblios_iterator();
132         $next = sub {
133             $records->next();
134         }
135     }
136     do_reindex($next, $Koha::ElasticSearch::BIBLIOS_INDEX);
137 }
138 if ($index_authorities) {
139     _log(1, "Indexing authorities\n");
140     if (@biblionumbers) {
141         $next = sub {
142             my $r = shift @biblionumbers;
143             return () unless defined $r;
144             my $a = Koha::Authority->get_from_authid($r);
145             return ($r, $a->record);
146         };
147     } else {
148         my $records = Koha::Authority->get_all_authorities_iterator();
149         $next = sub {
150             $records->next();
151         }
152     }
153     do_reindex($next, $Koha::ElasticSearch::AUTHORITIES_INDEX);
154 }
155
156 sub do_reindex {
157     my ( $next, $index_name ) = @_;
158
159     my $indexer = Koha::ElasticSearch::Indexer->new( { index => $index_name } );
160     if ($delete) {
161
162         # We know it's safe to not recreate the indexer because update_index
163         # hasn't been called yet.
164         $indexer->drop_index();
165     }
166
167     my $count        = 0;
168     my $commit_count = $commit;
169     my ( @id_buffer, @commit_buffer );
170     while ( my $record = $next->() ) {
171         my $id     = $record->id;
172         my $record = $record->record;
173         _log( 1, "$id\n" );
174         $count++;
175
176         push @id_buffer,     $id;
177         push @commit_buffer, $record;
178         if ( !( --$commit_count ) ) {
179             _log( 2, "Committing...\n" );
180             $indexer->update_index( \@id_buffer, \@commit_buffer );
181             $commit_count  = $commit;
182             @id_buffer     = ();
183             @commit_buffer = ();
184         }
185     }
186
187     # There are probably uncommitted records
188     $indexer->update_index( \@id_buffer, \@commit_buffer );
189     _log( 1, "$count records indexed.\n" );
190 }
191
192 # Output progress information.
193 #
194 #   _log($level, $msg);
195 #
196 # Will output $msg if the verbosity setting is set to $level or more. Will
197 # not include a trailing newline.
198 sub _log {
199     my ($level, $msg) = @_;
200
201     print $msg if ($verbose >= $level);
202 }