Data-Seek
view release on metacpan or search on metacpan
SYNOPSIS
use Data::Seek;
my $hash = {...};
my $seeker = Data::Seek->new(data => $hash);
my $result = $seeker->search(...);
my $data = $result->data;
DESCRIPTION
Data::Seek is used for querying complex data structures. This module
allows you to select and return specific node(s) in a hierarchical data
structure using a simple and intuitive query syntax. The results can be
returned as a list of values, or as a hash object in the same shape as
the original.
CONCEPT
The follow is a short and simple overview of the strategy and syntax
used by Data::Seek to query complex data structures. The overall idea
behind Data::Seek is to flatten/fold the data structure, reduce it by
applying a series patterns, then, unflatten/unfold and operate on the
new data structure. The introspection strategy is to flatten the data
structure producing a non-hierarchical data structure where its keys
represent endpoints (using dot-notation and colons to separate (and
denote) nested hash keys and array indices respectively) within the
structure.
ENCODING
During the processing of flattening a data structure with nested data,
the following data structure would be converted into a collection of
endpoint/value pairs.
{
'id' => 12345,
'patient' => {
'name' => {
'first' => 'Bob',
'last' => 'Bee'
}
},
'medications' => [{
'aceInhibitors' => [{
'name' => 'lisinopril',
'strength' => '10 mg Tab',
'dose' => '1 tab',
'route' => 'PO',
'sig' => 'daily',
'pillCount' => '#90',
'refills' => 'Refill 3'
}],
'antianginal' => [{
'name' => 'nitroglycerin',
'strength' => '0.4 mg Sublingual Tab',
'dose' => '1 tab',
'route' => 'SL',
'sig' => 'q15min PRN',
'pillCount' => '#30',
'refills' => 'Refill 1'
}],
}]
}
Given the aforementioned data structure, the following would be the
resulting flattened structure comprised of endpoint/value pairs.
{
'id' => 12345,
'medications:0.aceInhibitors:0.dose' => '1 tab',
'medications:0.aceInhibitors:0.name' => 'lisinopril',
'medications:0.aceInhibitors:0.pillCount' => '#90',
'medications:0.aceInhibitors:0.refills' => 'Refill 3',
'medications:0.aceInhibitors:0.route' => 'PO',
'medications:0.aceInhibitors:0.sig' => 'daily',
'medications:0.aceInhibitors:0.strength' => '10 mg Tab',
'medications:0.antianginal:0.dose' => '1 tab',
'medications:0.antianginal:0.name' => 'nitroglycerin',
'medications:0.antianginal:0.pillCount' => '#30',
'medications:0.antianginal:0.refills' => 'Refill 1',
'medications:0.antianginal:0.route' => 'SL',
'medications:0.antianginal:0.sig' => 'q15min PRN',
'medications:0.antianginal:0.strength' => '0.4 mg Sublingual Tab',
'patient.name.first' => 'Bob'
'patient.name.last' => 'Bee',
}
This structure provides the endpoint strings which will be matched
against using the querying strategy.
QUERYING
During the processing of querying the data structure, the criteria
(query expressions) are converted into a series of regular expressions
to be applied sequentially, filtering/reducing the endpoints and
producing a data set of matching nodes or throwing an exception
explaining the search failure.
* Node Expression
my $result = $seeker->search(...);
# given "id"
{ id => 12345 }
The node expression is a part of a criterion, which preforms an exact
match against a node in the data structure. It is a string which can
contain letters, numbers, and/or underscores.
* Step Expression
my $result = $seeker->search(...);
# given "patient.name.first"
{ patient => { name => { first => "Bob" } } }
# given "patient.name.last"
{ patient => { name => { last => "Bee" } } }
The step expression is a criterion, or part of a criterion, made up
of one or more node expressions separated using the period character,
which matches against nodes in the data structure. It is a string
which can contain letters, numbers, and/or underscores, separated
using periods.
* Index Expression
my $result = $seeker->search(...);
# given "medications:0.aceInhibitors:0.dose"
{ medications => [{ aceInhibitors => [{ dose => "1 tab" }] }] }
# given "medications:0.aceInhibitors:0.name"
{ medications => [{ aceInhibitors => [{ name => "lisinopril" }] }], }
# given "medications:0.aceInhibitors:0.pillCount"
{ medications => [{ aceInhibitors => [{ pillCount => "#90" }] }] }
The index expression is a criterion, or part of a criterion, having a
node expressions suffixed with a colon followed by a number denoting
that it should only match an array which has an index corresponding
to the numeric portion of the suffix. It is a string which can
contain letters, numbers, and/or underscores, suffixed with a
semi-colon followed by a number.
* Iterator Expression
my $result = $seeker->search(...);
# given "@medications.@aceInhibitors.dose"
{ medications => [{ aceInhibitors => [{ dose => "1 tab" }] }] }
# given "@medications.@aceInhibitors.name"
{ medications => [{ aceInhibitors => [{ name => "lisinopril" }] }], }
( run in 0.758 second using v1.01-cache-2.11-cpan-437f7b0c052 )