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 a module for traversing complex data structures. This
    module allows you to select specific node(s) in a hierarchical data
    structure using a criteria. A criteria is an expression consisting of
    one or more criterion. A criterion is the part of the criteria that is
    used to select node(s) to be returned in the result. Data::Seek is akin
    to Data::Dpath but with fewer features and a simple node selection
    syntax. Data::Seek node traversal is extremely fast, and it can throw
    exception objects which explain, in detail, why a search failed. This
    is very useful internally, and externally when processing foreign data
    structures where you need to provide detailed errors explaining how to
    resolve the missing or malformed data nodes.

CONCEPTS

    The follow is a short and simple overview of the strategy and syntax
    used by Data::Seek to query complex data strictures. The overall idea
    behind Data::Seek is to flatten/fold the data structure, preferably
    once, 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 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

        id
        patient
        medications

    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 "id"
        { id => 12345 }
    
        # 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" }] }], }
    
        # given "@medications.@aceInhibitors.pillCount"
        { medications => [{ aceInhibitors => [{ pillCount => "#90" }] }] }

    The iteration expression is a criterion, or part of a criterion, having
    a node expressions preceded by an "at" character (ampersand) denoting
    that the node expression should match all nodes in the data structure
    which are mapped to array objects. It is a string which can contain
    letters, numbers, and/or underscores, preceded by a single ampersand
    character.

 Wildcard Expression

        my $result = $seeker->search(...);
    
        # given "*"
        { id => 12345 }
    
        # given "*.*.first"
        { patient => { name => { first => "Bob" } } }
    
        # given "*.*.last"
        { patient => { name => { last => "Bee" } } }
    
        # given "patient.*.first"
        { patient => { name => { first => "Bob" } } }
    
        # given "patient.*.last"
        { patient => { name => { last => "Bee" } } }
    
        # given "@*.@*.pillCount"
        {
            medications => [{
                aceInhibitors => [{ pillCount => "#90" }],
                antianginal   => [{ pillCount => "#30" }],
            }],
        }

    The wildcard expression is a criterion, or part of a criterion, which
    matches against a single node having a single "star" character match
    and represent one node expression. It is a string which can contain
    letters, numbers, underscores, and/or a single star character.

 Greedy-Wildcard Expression

        my $result = $seeker->search(...);
    
        # given "**.first"
        { patient => { name => { first => "Bob" } } }
    
        # given "**.last"
        { patient => { name => { last => "Bee" } } }
    
        # given "patient.**"
        { patient => { name => { first => "Bob", last => "Bee" } } }
    
        # given "medications**.pillCount"
        {
            medications => [{
                aceInhibitors => [{ pillCount => "#90" }],
                antianginal   => [{ pillCount => "#30" }],
            }],
        }

    The greedy-wildcard expression is a criterion, or part of a criterion,
    which matches against any multitude of nodes having a double "star"
    character match and represent one or more of any character. It is a
    string which can contain letters, numbers, underscores, and/or a double
    star character.

        $seeker->cache;
        $seeker->cache(1);

    Encode the data structure and cache the result. Allows multiple queries
    to execute faster. Caching is disabled by default.

        $seeker->data;
        $seeker->data(Data::Seek::Data->new(...));

    The data structure to be introspected, must be a hash reference,
    blessed or not, which defaults to or becomes a Data::Seek::Data object.

        $seeker->ignore;
        $seeker->ignore(1);

    Bypass exceptions thrown when a criterion is invalid or no data matches
    can be found.

        my @criteria = ('id', 'person.name.*');
        my $result   = $seeker->search(@criteria);

    Prepare a search object to use the supplied criteria and return a
    result object. Introspection is triggered when the result object is
    enacted. See Data::Seek::Search::Result for usage information.

POD ERRORS

    Hey! The above document had some coding errors, which are explained
    below:

    Around line 229:

      Unknown directive: =attr

    Around line 237:

      Unknown directive: =attr

    Around line 245:

      Unknown directive: =attr

    Around line 253:

      Unknown directive: =method

