File Coverage

blib/lib/Catmandu/Fix/Bind/hashmap.pm
Criterion Covered Total %
statement 44 45 97.7
branch 15 16 93.7
condition 4 5 80.0
subroutine 9 9 100.0
pod 0 1 0.0
total 72 76 94.7


line stmt bran cond sub pod time code
1              
2             use Catmandu::Sane;
3 1     1   4850  
  1         2  
  1         6  
4             our $VERSION = '1.2018';
5              
6             use Moo;
7 1     1   5 use Catmandu::Util qw(:is);
  1         2  
  1         5  
8 1     1   344 use namespace::clean;
  1         1  
  1         220  
9 1     1   6 use Catmandu::Fix::Has;
  1         7  
  1         25  
10 1     1   888  
  1         2  
  1         5  
11             with 'Catmandu::Fix::Bind', 'Catmandu::Fix::Bind::Group';
12              
13             has exporter => (fix_opt => 1);
14             has store => (fix_opt => 1);
15             has uniq => (fix_opt => 1, default => sub {0});
16             has count => (fix_opt => 1);
17             has join => (fix_opt => 1);
18             has extra_args => (fix_opt => 'collect');
19             has hash => (is => 'lazy');
20              
21             +{};
22             }
23 12     12   102  
24             my ($self, $key, $val) = @_;
25             if ($self->count) {
26             $self->hash->{$key} += 1;
27 9     9 0 16 }
28 9 100       38 elsif ($self->uniq) {
    100          
29 3         39 $self->hash->{$key}->{$val} = 1;
30             }
31             else {
32 3         39 push @{$self->hash->{$key}}, $val;
33             }
34             }
35 3         4  
  3         42  
36             my ($self, $data, $code) = @_;
37              
38             $data = $code->($data);
39              
40             my $key = $data->{key};
41             my $value = $data->{value};
42              
43             if (defined $key) {
44             if (is_string($key)) {
45             $self->add_to_hash($key, $value);
46             }
47             elsif (is_array_ref($key)) {
48             for (@$key) {
49             $self->add_to_hash($_, $value);
50             }
51             }
52             else {
53             warn "$key is not a string or array for $value";
54             }
55             }
56              
57             $data;
58             }
59              
60             my ($self) = @_;
61             my $h = $self->hash;
62             my $e;
63             my $args = $self->extra_args // {};
64              
65 12     12   1724 if ($self->store) {
66 12         203 $e = Catmandu->store($self->store, %$args);
67 12         32 }
68 12   50     36 elsif ($self->exporter) {
69             $e = Catmandu->exporter($self->exporter, %$args);
70 12 50       53 }
    100          
71 0         0 else {
72             $e = Catmandu->exporter('JSON', line_delimited => 1);
73             }
74 3         17  
75             my $sorter = $self->count ? sub {$h->{$b} <=> $h->{$a}} : sub {$a cmp $b};
76              
77 9         34 my $id = 0;
78             for (sort $sorter keys %$h) {
79             my $v;
80 12 100   1   80  
  1         4  
  2         8  
81             if ($self->count) {
82 12         19 $v = $h->{$_};
83 12         43 }
84 6         23 elsif ($self->uniq) {
85             $v = [sort keys %{$h->{$_}}];
86 6 100       18 }
    100          
87 2         4 else {
88             $v = $h->{$_};
89             }
90 2         4  
  2         7  
91             if (is_array_ref($v) && $self->join) {
92             $v = join $self->join, @$v;
93 2         3 }
94              
95             $e->add({_id => $_, value => $v});
96 6 100 100     28 }
97 2         8  
98             $e->commit;
99             }
100 6         108  
101             1;
102              
103 12         206  
104             =pod
105              
106             =head1 NAME
107              
108             Catmandu::Fix::Bind::hashmap - a binder to add key/value pairs to an internal hashmap
109              
110             =head1 SYNOPSIS
111              
112             # Find non unique ISBN numbers in the record stream
113             do hashmap(join: ',')
114             copy_field(isbn,key)
115             copy_field(_id,value)
116             end
117              
118             # will export to the JSON exporter a hash map containing all isbn occurrences in the stream
119              
120             { "_id": "9781565920422" , "value": "rec0001,rec0329,rec1032" }
121             { "_id": "9780596004927" , "value": "rec0718" }
122              
123             # Ignore the values. Count the number of ISBN occurrences in a stream
124             # File: count.fix:
125             do hashmap(count: 1)
126             copy_field(isbn,key)
127             end
128              
129             # Use the Null exporter to suppress the normal output
130             $ cat /tmp/data.json | catmandu convert JSON --fix count.fix to Null
131              
132             =head1 DESCRIPTION
133              
134             The hashmap binder will insert all key/value pairs given to a internal hashmap
135             that can be exported using an Catmandu::Exporter.
136              
137             The 'key' fields in the internal hashmap will be exported as '_id' field.
138              
139             If the key in the hashmap Bind is an ARRAY, then multiple key/value pairs will
140             be inserted into the hashmap.
141              
142             By default all the values will be added as an array to the hashmap. Every key
143             will have one or more values. Use the 'join' parameter to create a string
144             out of this array.
145              
146             =head1 CONFIGURATION
147              
148             =head2 exporter: EXPORTER
149              
150             The name of an exporter to send the results to. Default: JSON Extra parameters can be added:
151              
152             do hashmap(exporter: JSON, file:/tmp/data.json, count: 1)
153             ...
154             end
155              
156             =head2 store: STORE
157              
158             Send the output to a store instead of an exporter. Extra parameters can be added:
159              
160             do hashmap(store: MongoDB, database_name: test, bag: data, count: 1)
161             ...
162             end
163              
164             =head2 uniq: 0|1
165              
166             When set to 1, then all values in the key 'value' will be made unique
167              
168             =head2 join: CHAR
169              
170             Join all the values of a key using a delimiter.
171              
172             =head2 count: 0|1
173              
174             Don't store the values only count the number of key occurrences.
175              
176             =head1 SEE ALSO
177              
178             L<Catmandu::Fix::Bind>
179              
180             =cut