Bug 24823: Fix spelling error and remove last of Catmandu
[koha-ffzg.git] / Koha / SearchEngine / Elasticsearch / Browse.pm
1 package Koha::SearchEngine::Elasticsearch::Browse;
2
3 # Copyright 2015 Catalyst IT
4 #
5 # This file is part of Koha.
6 #
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20 =head1 NAME
21
22 Koha::SearchEngine::ElasticSearch::Browse - browse functions for Elasticsearch
23
24 =head1 SYNOPSIS
25
26     my $browser =
27       Koha::SearchEngine::Elasticsearch::Browse->new( { index => 'biblios' } );
28     my $results = $browser->browse(
29         'prefi', 'title',
30         {
31             results   => '500',
32             fuzziness => 2,
33         }
34     );
35     foreach my $r (@$results) {
36         push @hits, $r->{text};
37     }
38
39 =head1 DESCRIPTION
40
41 This provides an easy interface to the "browse" functionality. Essentially,
42 it does a fast prefix search on defined fields. The fields have to be marked
43 as "suggestible" in the database when indexing takes place.
44
45 =head1 METHODS
46
47 =cut
48
49 use base qw(Koha::SearchEngine::Elasticsearch);
50 use Modern::Perl;
51
52 =head2 browse
53
54     my $results = $browser->browse($prefix, $field, \%options);
55
56 Does a prefix search for C<$prefix>, looking in C<$field>. Options are:
57
58 =over 4
59
60 =item count
61
62 The number of results to return. For Koha browse purposes, this should
63 probably be fairly high. Defaults to 500.
64
65 =item fuzziness
66
67 How much allowing for typos and misspellings is done. If 0, then it must match
68 exactly. If unspecified, it defaults to '1', which is probably the most useful.
69 Otherwise, it is a number specifying the Levenshtein edit distance relative to
70 the string length, according to the following lengths:
71
72 =over 4
73
74 =item 0..2
75
76 must match exactly
77
78 =item 3..5
79
80 C<fuzziness> edits allowed
81
82 =item >5
83
84 C<fuzziness>+1 edits allowed
85
86 =back
87
88 In all cases the maximum number of edits allowed is two (an elasticsearch
89 restriction.)
90
91 =back
92
93 =head3 Returns
94
95 This returns an arrayref of hashrefs. Each hashref contains a "text" element
96 that contains the field as returned. There may be other fields in that
97 hashref too, but they're less likely to be important.
98
99 The array will be ordered as returned from Elasticsearch, which seems to be
100 in order of some form of relevance.
101
102 =cut
103
104 sub browse {
105     my ($self, $prefix, $field, $options) = @_;
106
107     my $query = $self->_build_query($prefix, $field, $options);
108     my $elasticsearch = $self->get_elasticsearch();
109     my $conf = $self->get_elasticsearch_params();
110     my $results = $elasticsearch->search(
111         index => $conf->{index_name},
112         body => $query
113     );
114
115     return $results->{suggest}{suggestions}[0]{options};
116 }
117
118 =head2 _build_query
119
120     my $query = $self->_build_query($prefix, $field, $options);
121
122 Arguments are the same as for L<browse>. This will return a query structure
123 for elasticsearch to use.
124
125 =cut
126
127 sub _build_query {
128     my ( $self, $prefix, $field, $options ) = @_;
129
130     $options = {} unless $options;
131     my $f = $options->{fuzziness} // 1;
132     my $l = length($prefix);
133     my $fuzzie;
134     if ( $l <= 2 ) {
135         $fuzzie = 0;
136     }
137     elsif ( $l <= 5 ) {
138         $fuzzie = $f;
139     }
140     else {
141         $fuzzie = $f + 1;
142     }
143     $fuzzie = 2 if $fuzzie > 2;
144
145     my $size = $options->{count} // 500;
146     my $query = {
147         # this is an annoying thing, if we set size to 0 it gets rewritten
148         # to 10. There's a bug somewhere in one of the libraries.
149         size    => 1,
150         suggest => {
151             suggestions => {
152                 text       => $prefix,
153                 completion => {
154                     field => $field . '__suggestion',
155                     size  => $size,
156                     fuzzy => {
157                         fuzziness => $fuzzie,
158                     }
159                 }
160             }
161         }
162     };
163     return $query;
164 }
165
166 1;
167
168 __END__
169
170 =head1 AUTHOR
171
172 =over 4
173
174 =item Robin Sheat << <robin@catalyst.net.nz> >>
175
176 =back
177
178 =cut