File Coverage

blib/lib/Catmandu/Searchable.pm
Criterion Covered Total %
statement 16 16 100.0
branch n/a
condition n/a
subroutine 8 8 100.0
pod 0 4 0.0
total 24 28 85.7


line stmt bran cond sub pod time code
1              
2             use Catmandu::Sane;
3 3     3   90370  
  3         7  
  3         21  
4             our $VERSION = '1.2018';
5              
6             use Catmandu::Util qw(is_natural is_positive);
7 3     3   23 use Moo::Role;
  3         6  
  3         162  
8 3     3   13 use namespace::clean;
  3         8  
  3         18  
9 3     3   1079  
  3         6  
  3         27  
10             with 'Catmandu::Logger';
11              
12             requires 'search';
13             requires 'searcher';
14             requires 'delete_by_query';
15              
16             has default_limit => (is => 'ro', builder => 'default_default_limit');
17             has maximum_limit => (is => 'ro', builder => 'default_maximum_limit');
18             has maximum_offset => (is => 'ro');
19              
20              
21 6     6 0 12250  
22 6     6 0 86  
23             my $AROUND_SEARCH = sub {
24 7     7 0 1370 my ($orig, $self, %args) = @_;
25             $args{limit} = $self->default_limit unless is_natural($args{limit});
26 5     5 0 9 $args{start} = 0 unless is_natural($args{start});
27             $args{start} += 0;
28             $args{limit} += 0;
29             if ($args{limit} > $self->maximum_limit) {
30             $args{limit} = $self->maximum_limit;
31             }
32             if (is_positive(my $page = delete $args{page})) {
33             $args{start} = ($page - 1) * $args{limit};
34             }
35              
36             $args{query} = $self->normalize_query($args{query});
37             $args{sort} = $self->normalize_sort($args{sort});
38              
39             defined $args{$_} || delete $args{$_} for keys %args;
40              
41             $self->log->debugf("called with params %s", [%args]);
42              
43             # TODO apply maximum offset more cleanly
44             if (my $max_offset = $self->maximum_offset) {
45             my $start = $args{start};
46             my $limit = $args{limit};
47             if ($start + $limit > $max_offset) {
48             $limit = ($max_offset - $start) + 1;
49             $limit = 0 if $limit < 0;
50             }
51             my $hits = $orig->($self, %args, limit => $limit);
52             $hits->{limit} = $args{limit};
53             $hits->{maximum_offset} = $max_offset;
54             return $hits;
55             }
56              
57             $orig->($self, %args);
58             };
59              
60             around search => $AROUND_SEARCH;
61             around searcher => $AROUND_SEARCH;
62              
63             around delete_by_query => sub {
64             my ($orig, $self, %args) = @_;
65              
66             $args{query} = $self->normalize_query($args{query});
67              
68             $self->log->debugf("called with params %s", [%args]);
69             $orig->($self, %args);
70             return;
71             };
72              
73             1;
74              
75              
76             =pod
77              
78             =head1 NAME
79              
80             Catmandu::Searchable - Optional role for searchable stores
81              
82             =head1 SYNOPSIS
83              
84             my $store = Catmandu::Store::Solr->new();
85              
86             # Return one page of search results (page size = 1000)
87             my $hits = $store->bag->search(
88             query => 'dna' ,
89             start => 0 ,
90             limit => 100 ,
91             sort => 'title desc',
92             );
93              
94             # Return all the search results as iterator
95             my $it = $store->bag->searcher(query => 'dna');
96             $it->each(sub { ...});
97              
98             $store->bag->delete_by_query(query => 'dna');
99              
100             =head1 CONFIGURATION
101              
102             =over
103              
104             =item default_limit
105              
106             The default value for C<limit>. By default this is C<10>.
107              
108             =item maximum_limit
109              
110             The maximum allowed value for C<limit>. By default this is C<1000>.
111              
112             =item maximum_offset
113              
114             The maximum allowed offset. When set no hits will be returned after hit offset
115             is greater than C<maximum_offset>, this to avoid deep paging problems.
116             Pagination values will be also be adjusted accordingly.
117              
118             =back
119              
120             =head1 METHODS
121              
122             =head2 search(query => $query, start => $start, page => $page, limit => $num, sort => $sort)
123              
124             Search the database and returns a L<Catmandu::Hits> on success. The Hits represents one
125             result page of at most $num results. The $query and $sort should implement the
126             query and sort syntax of the underlying search engine.
127              
128             Optionally provide the index of the first result using the C<start> option, or the starting page using
129             the C<page> option. The number of records in a result page can be set using the C<limit> option. Sorting
130             options are being sent verbatim to the underlying search engine.
131              
132             =head2 searcher(query => $query, start => $start, limit => $num, sort => $sort, cql_query => $cql)
133              
134             Search the database and return a L<Catmandu::Iterable> on success. This iterator can be
135             used to loop over the complete result set. The $query and $sort should implement the
136             query and sort syntax of the underlying search engine.
137              
138             Optionally provide the index of the first result using the C<start> option. The number of records in
139             a page can be set using the C<limit> option. Sorting options are being sent verbatim to the underlying
140             search engine.
141              
142             =head2 delete_by_query(query => $query)
143              
144             Delete items from the database that match $query
145              
146             =head1 CQL support
147              
148             Stores that are support the L<CQL query language|https://www.loc.gov/standards/sru/cql/> also accept the C<cql_query>
149             and C<sru_sortkeys> arguments. See L<Catmandu::CQLSearchable> for more information.
150              
151             =head1 SEE ALSO
152              
153             L<Catmandu::CQLSearchable>, L<Catmandu::Hits>, L<Catmandu::Paged>
154              
155             =cut