File Coverage

blib/lib/Catmandu/Store/Solr/Bag.pm
Criterion Covered Total %
statement 27 72 37.5
branch 0 20 0.0
condition 0 14 0.0
subroutine 9 18 50.0
pod 0 6 0.0
total 36 130 27.6


line stmt bran cond sub pod time code
1             package Catmandu::Store::Solr::Bag;
2              
3 3     3   14 use Catmandu::Sane;
  3         4  
  3         24  
4 3     3   660 use Catmandu::Util qw(:is);
  3         6  
  3         783  
5 3     3   17 use Carp qw(confess);
  3         4  
  3         148  
6 3     3   756 use Catmandu::Hits;
  3         39116  
  3         88  
7 3     3   1232 use Catmandu::Store::Solr::Searcher;
  3         8  
  3         90  
8 3     3   1540 use Catmandu::Store::Solr::CQL;
  3         7  
  3         98  
9 3     3   18 use Catmandu::Error;
  3         4  
  3         71  
10 3     3   10 use Moo;
  3         4  
  3         10  
11 3     3   813 use MooX::Aliases;
  3         3  
  3         23  
12              
13             our $VERSION = "0.0302";
14              
15             with 'Catmandu::Bag';
16             with 'Catmandu::CQLSearchable';
17             with 'Catmandu::Buffer';
18              
19             has cql_mapping => (is => 'ro');
20              
21             has bag_key => (is => 'lazy', alias => 'bag_field');
22              
23             sub _build_bag_key {
24 0     0     $_[0]->store->bag_key;
25             }
26              
27             sub generator {
28 0     0 0   my ($self) = @_;
29 0           my $store = $self->store;
30 0           my $name = $self->name;
31 0           my $limit = $self->buffer_size;
32 0           my $bag_field = $self->bag_field;
33 0           my $query = qq/$bag_field:"$name"/;
34             sub {
35 0     0     state $start = 0;
36 0           state $hits;
37 0 0 0       unless ($hits && @$hits) {
38             $hits = $store->solr->search($query, {
39             start => $start,
40             rows => $limit,
41             defType => "lucene",
42             facet => "false",
43             spellcheck => "false"
44 0           })->content->{response}{docs};
45 0           $start += $limit;
46             }
47 0   0       my $hit = shift(@$hits) || return;
48 0           $self->map_fields($hit);
49 0           $hit;
50 0           };
51             }
52              
53             sub count {
54 0     0 0   my ($self) = @_;
55 0           my $name = $self->name;
56 0           my $bag_field = $self->bag_field;
57 0           my $res = $self->store->solr->search(
58             qq/$bag_field:"$name"/,
59             {
60             rows => 0,
61             facet => "false",
62             spellcheck => "false",
63             defType => "lucene",
64             }
65             );
66 0           $res->content->{response}{numFound};
67             }
68              
69             sub get {
70             my ($self, $id) = @_;
71             my $name = $self->name;
72             my $id_field = $self->id_field;
73             my $bag_field = $self->bag_field;
74             my $res = $self->store->solr->search(
75             qq/$bag_field:"$name" AND $id_field:"$id"/,
76             {
77             rows => 1,
78             facet => "false",
79             spellcheck => "false",
80             defType => "lucene",
81             }
82             );
83             my $hit = $res->content->{response}{docs}->[0] || return;
84             $self->map_fields($hit);
85             $hit;
86             }
87              
88             sub add {
89             my ($self, $data) = @_;
90              
91             my $bag_field = $self->bag_field;
92              
93             my @fields = (WebService::Solr::Field->new($bag_field => $self->name));
94              
95             for my $key (keys %$data) {
96             next if $key eq $bag_field;
97             my $val = $data->{$key};
98             if (is_array_ref($val)) {
99             is_value($_) && push @fields,
100             WebService::Solr::Field->new($key => $_)
101             foreach @$val;
102             }
103             elsif (is_value($val)) {
104             push @fields, WebService::Solr::Field->new($key => $val);
105             }
106             }
107              
108             $self->buffer_add(WebService::Solr::Document->new(@fields));
109              
110             if ($self->buffer_is_full) {
111             $self->commit;
112             }
113             }
114              
115             sub delete {
116             my ($self, $id) = @_;
117             my $name = $self->name;
118             my $id_field = $self->id_field;
119             my $bag_field = $self->bag_field;
120             $self->store->solr->delete_by_query(qq/$bag_field:"$name" AND $id_field:"$id"/);
121             }
122              
123             sub delete_all {
124             my ($self) = @_;
125             my $name = $self->name;
126             my $bag_field = $self->bag_field;
127             $self->store->solr->delete_by_query(qq/$bag_field:"$name"/);
128             }
129             sub delete_by_query {
130             my ($self, %args) = @_;
131             my $name = $self->name;
132             my $bag_field = $self->bag_field;
133             $self->store->solr->delete_by_query(qq/$bag_field:"$name" AND ($args{query})/);
134             }
135              
136             sub commit {
137             my ($self) = @_;
138             my $solr = $self->store->solr;
139             my $err;
140             if ($self->buffer_used) {
141             eval { $solr->add($self->buffer) } or push @{ $err ||= [] }, $@;
142             $self->clear_buffer;
143             }
144             unless($self->store->{_tx}){
145             eval { $solr->commit } or push @{ $err ||= [] }, $@;
146             }
147              
148             if(defined $err && $self->store->on_error eq 'throw'){
149             Catmandu::Error->throw($err->[0]);
150             }
151             }
152              
153             sub search {
154             my ($self, %args) = @_;
155              
156             my $query = delete $args{query};
157             my $start = delete $args{start};
158             my $limit = delete $args{limit};
159             my $bag = delete $args{reify};
160              
161             my $name = $self->name;
162             my $id_field = $self->id_field;
163             my $bag_field = $self->bag_field;
164              
165             my $bag_fq = qq/{!type=lucene}$bag_field:"$name"/;
166              
167             if ( $args{fq} ) {
168             if (is_array_ref( $args{fq})) {
169             $args{fq} = [ $bag_fq , @{ $args{fq} } ];
170             }
171             else {
172             $args{fq} = [$bag_fq, $args{fq}];
173             }
174             } else {
175             $args{fq} = $bag_fq;
176             }
177              
178             my $res = $self->store->solr->search($query, {%args, start => $start, rows => $limit});
179              
180             my $set = $res->content->{response}{docs};
181              
182             if ($bag) {
183             $set = [map { $bag->get($_->{$id_field}) } @$set];
184             } else {
185             $self->map_fields($_) for (@$set);
186             }
187              
188             my $hits = Catmandu::Hits->new({
189             limit => $limit,
190             start => $start,
191             total => $res->content->{response}{numFound},
192             hits => $set,
193             });
194              
195             if ($res->facet_counts) {
196             $hits->{facets} = $res->facet_counts;
197             }
198              
199             if ($res->spellcheck) {
200             $hits->{spellcheck} = $res->spellcheck;
201             }
202             if ( $res->content->{highlighting} ) {
203             $hits->{highlighting} = $res->content->{highlighting};
204             }
205              
206             $hits;
207             }
208              
209             sub searcher {
210             my ($self, %args) = @_;
211             Catmandu::Store::Solr::Searcher->new(%args, bag => $self);
212             }
213              
214             sub translate_sru_sortkeys {
215 0     0 0   my ($self, $sortkeys) = @_;
216 0           join(',', grep { defined $_ } map { $self->_translate_sru_sortkey($_) } split /\s+/, $sortkeys);
  0            
  0            
217             }
218             sub _translate_sru_sortkey {
219 0     0     my ($self, $sortkey) = @_;
220 0           my ($field, $schema, $asc) = split /,/, $sortkey;
221 0 0         $field || return;
222 0 0         if (my $map = $self->cql_mapping) {
223 0           $field = lc $field;
224 0 0         $field =~ s/(?<=[^_])_(?=[^_])//g if $map->{strip_separating_underscores};
225 0   0       $map = $map->{indexes} || return;
226 0   0       $map = $map->{$field} || return;
227 0 0         $map->{sort} || return;
228 0 0 0       if (ref $map->{sort} && $map->{sort}{field}) {
    0          
    0          
229 0           $field = $map->{sort}{field};
230             } elsif (ref $map->{field}) {
231 0           $field = $map->{field}->[0];
232             } elsif ($map->{field}) {
233 0           $field = $map->{field};
234             }
235             }
236 0   0       $asc //= 1;
237 0 0         "${field} ".($asc ? "asc" : "desc");
238             }
239             sub translate_cql_query {
240 0     0 0   my($self,$query) = @_;
241 0           Catmandu::Store::Solr::CQL->new(mapping => $self->cql_mapping)->parse($query);
242             }
243              
244             sub normalize_query {
245 0 0   0 0   $_[1] || "{!type=lucene}*:*";
246             }
247              
248             sub map_fields {
249 0     0 0   my ($self, $item) = @_;
250 0           delete $item->{$self->bag_field};
251             }
252              
253             =head1 SEE ALSO
254              
255             L<Catmandu::Bag>, L<Catmandu::Searchable>
256              
257             =cut
258              
259             1;