File Coverage

lib/Apache/Solr/JSON.pm
Criterion Covered Total %
statement 27 123 21.9
branch 0 32 0.0
condition 0 41 0.0
subroutine 9 23 39.1
pod 3 5 60.0
total 39 224 17.4


line stmt bran cond sub pod time code
1             # Copyrights 2012-2022 by [Mark Overmeer].
2             # For other contributors see ChangeLog.
3             # See the manual pages for details on the licensing terms.
4             # Pod stripped from pm file by OODoc 2.03.
5             # This code is part of distribution Apache-Solr. Meta-POD processed with
6             # OODoc into POD and HTML manual-pages. See README.md
7             # Copyright Mark Overmeer. Licensed under the same terms as Perl itself.
8              
9             package Apache::Solr::JSON;
10 1     1   724 use vars '$VERSION';
  1         1  
  1         43  
11             $VERSION = '1.07';
12              
13 1     1   4 use base 'Apache::Solr';
  1         1  
  1         74  
14              
15 1     1   5 use warnings;
  1         1  
  1         20  
16 1     1   3 use strict;
  1         1  
  1         18  
17              
18 1     1   13 use Log::Report qw(solr);
  1         2  
  1         5  
19              
20 1     1   225 use Apache::Solr::Result ();
  1         2  
  1         11  
21 1     1   4 use HTTP::Request ();
  1         1  
  1         19  
22 1     1   623 use JSON ();
  1         6811  
  1         24  
23 1     1   8 use Scalar::Util qw(blessed);
  1         1  
  1         967  
24              
25              
26             sub init($)
27 0     0 0   { my ($self, $args) = @_;
28 0   0       $args->{format} ||= 'JSON';
29 0           $self->SUPER::init($args);
30              
31 0   0       $self->{ASJ_json} = $args->{json} || JSON->new->utf8;
32 0           $self;
33             }
34              
35             #---------------
36              
37 0     0 1   sub json() {shift->{ASJ_json}}
38              
39             #--------------------------
40              
41             sub _select($$)
42 0     0     { my ($self, $args, $params) = @_;
43              
44             # select may be called more than once, but do not add wt each time
45             # again.
46 0           my @params = @$params;
47 0           my %params = @params;
48 0           unshift @params, wt => 'json';
49              
50 0           my $endpoint = $self->endpoint('select', params => \@params);
51 0           my $result = Apache::Solr::Result->new(%$args,
52             params => \@params, endpoint => $endpoint, core => $self);
53 0           $self->request($endpoint, $result);
54              
55 0 0         if(my $dec = $result->decoded)
56             { # JSON uses different names!
57 0           my $r = $dec->{result} = delete $dec->{response};
58 0           $r->{doc} = delete $r->{docs};
59             }
60 0           $result;
61             }
62              
63             sub _extract($$$)
64 0     0     { my ($self, $params, $data, $ct) = @_;
65 0           my @params = (wt => 'json', @$params);
66 0           my $endpoint = $self->endpoint('update/extract', params => \@params);
67 0           my $result = Apache::Solr::Result->new(params => \@params
68             , endpoint => $endpoint, core => $self);
69 0           $self->request($endpoint, $result, $data, $ct);
70 0           $result;
71             }
72              
73             sub _add($$$)
74 0     0     { my ($self, $docs, $attrs, $params) = @_;
75 0   0       $attrs ||= {};
76 0   0       $params ||= {};
77              
78 0           my $sv = $self->serverVersion;
79 0 0         $sv ge '3.1' or error __x"solr version too old for updates in JSON syntax";
80              
81 0           my @params = (wt => 'json', %$params);
82 0 0         my $endpoint = $self->endpoint
83             ( ($sv lt '4.0' ? 'update/json' : 'update')
84             , params => \@params
85             );
86 0           my $result = Apache::Solr::Result->new(params => \@params
87             , endpoint => $endpoint, core => $self);
88              
89             # We cannot create HASHes with twice the same key in Perl, so cannot
90             # produce the syntax for adding multiple documents. Try to save it.
91             delete $attrs->{boost}
92 0 0 0       if $attrs->{boost} && $attrs->{boost}==1.0;
93              
94             exists $attrs->{$_} && ($params->{$_} = delete $attrs->{$_})
95 0   0       for qw/commit commitWithin overwrite boost/;
96              
97 0           my $add;
98 0 0         if(@$docs==1)
    0          
99 0           { $add = {add => {%$attrs, doc => $self->_doc2json($docs->[0])}} }
100             elsif(keys %$attrs)
101             { # in combination with attributes only
102 0           error __x"unable to add more than one doc with JSON interface";
103             }
104             else
105 0           { $add = [ map $self->_doc2json($_), @$docs ] }
106              
107 0           $self->request($endpoint, $result, $add);
108 0           $result;
109             }
110              
111             sub _doc2json($)
112 0     0     { my ($self, $this) = @_;
113 0           my %doc;
114 0           foreach my $fieldname ($this->fieldNames)
115 0           { my @f;
116 0           foreach my $field ($this->fields($fieldname))
117 0   0       { my $update = $field->{update} || 'value';
118 0   0       my $boost = $field->{boost} || 1.0;
119              
120 0 0 0       undef $boost
121             if $boost > 0.9999 && $boost < 1.0001;
122              
123             push @f
124             , ! defined $boost && $update eq 'value'
125             ? $field->{content}
126             : defined $boost
127             ? +{ boost => $boost, $update => $field->{content} }
128 0 0 0       : +{ $update => $field->{content} };
    0          
129             }
130             # we have to combine multi-fields into ARRAYS
131 0 0         $doc{$fieldname} = @f > 1 ? \@f : $f[0];
132             }
133              
134 0           \%doc;
135             }
136              
137 0     0     sub _commit($) { my ($s, $attr) = @_; $s->simpleUpdate(commit => $attr) }
  0            
138 0     0     sub _optimize($) { my ($s, $attr) = @_; $s->simpleUpdate(optimize => $attr) }
  0            
139 0     0     sub _delete($$) { my $self = shift; $self->simpleUpdate(delete => @_) }
  0            
140 0     0     sub _rollback() { shift->simpleUpdate('rollback') }
141              
142             sub _terms($)
143 0     0     { my ($self, $terms) = @_;
144              
145 0           my @params = (wt => 'json', @$terms);
146 0           my $endpoint = $self->endpoint('terms', params => \@params);
147 0           my $result = Apache::Solr::Result->new(params => \@params
148             , endpoint => $endpoint, core => $self);
149              
150 0           $self->request($endpoint, $result);
151              
152 0   0       my $table = $result->decoded->{terms} || {};
153 0 0         $table = {@$table} if ref $table eq 'ARRAY'; # bug in Solr 1.4
154              
155 0           while(my ($field, $terms) = each %$table)
156             { # repack array-of-pairs into array-of-arrays-of-pair
157 0           my @pairs = @$terms;
158 0           my @terms;
159 0           push @terms, [shift @pairs, shift @pairs] while @pairs;
160 0           $result->terms($field => \@terms);
161             }
162              
163 0           $result;
164             }
165              
166             #--------------------------
167              
168             sub request($$;$$)
169 0     0 0   { my ($self, $url, $result, $body, $body_ct) = @_;
170              
171 0 0 0       if(ref $body && ref $body ne 'SCALAR')
172 0   0       { $body_ct ||= 'application/json; charset=utf-8';
173 0           $body = \$self->json->encode($body);
174             }
175              
176             # Solr server 3.6.2 seems not to detect the JSON input from the
177             # body content, so requires this work-around
178             # https://solr.apache.org/guide/6_6/uploading-data-with-index-handlers.html#UploadingDatawithIndexHandlers-JSONUpdateConveniencePaths
179 0           $url =~ s!/update\?!/update/json?!;
180              
181 0           my $resp = $self->SUPER::request($url, $result, $body, $body_ct);
182 0           my $ct = $resp->content_type;
183              
184             # At least until Solr 4.0 response ct=text/plain while producing JSON
185             # $ct =~ m/json/i
186             # or error __x"answer from solr server is not json but {type}"
187             # , type => $ct;
188              
189             #warn $resp->decoded_content;
190 0   0       my $dec = $self->json->decode($resp->decoded_content || $resp->content);
191              
192             #use Data::Dumper;
193             #warn Dumper $dec;
194 0           $result->decoded($dec);
195 0           $result;
196             }
197              
198              
199             sub simpleUpdate($$;$)
200 0     0 1   { my ($self, $command, $attrs, $content) = @_;
201              
202 0           my $sv = $self->serverVersion;
203 0 0         $sv ge '3.1' or error __x"solr version too old for updates in JSON syntax";
204              
205 0   0       $attrs ||= {};
206 0           my @params = (wt => 'json', commit => delete $attrs->{commit});
207 0 0         my $endpoint = $self->endpoint
208             ( ($sv lt '4.0' ? 'update/json' : 'update')
209             , params => \@params
210             );
211 0           my $result = Apache::Solr::Result->new(params => \@params
212             , endpoint => $endpoint, core => $self);
213              
214 0 0         my %params = (%$attrs
    0          
215             , (!$content ? () : ref $content eq 'HASH' ? %$content : @$content));
216 0           my $doc = $self->simpleDocument($command, \%params);
217 0           $self->request($endpoint, $result, $doc);
218 0           $result;
219             }
220              
221              
222             sub simpleDocument($;$$)
223 0     0 1   { my ($self, $command, $attrs, $content) = @_;
224 0   0       $attrs ||= {};
225 0   0       $content ||= {};
226 0           +{ $command => { %$attrs, %$content } }
227             }
228              
229             1;