ravi45722 has asked for the wisdom of the Perl Monks concerning the following question:

When I use search query its returning a hash value reference. I am decoding it with deference

But later I cant able to access the 'formula' variable in the below mentioned hash.
$VAR1 = { '_source' => { 'sheets' => { 'sheet1' => { 'Sheet_Name' => ' +Ex-Sheet', 'formulates' => [ { +'0' => { + 'colName' => 'Ex-Col1', + 'formula' => '((DelvSts = Deleted + RcdTyp = DelAck) & RcdTy +p = DelRecpt)', + 'total' => 'false' + } }, { +'1' => { + 'colName' => 'Ex-col2', + 'formula' => '((DelvSts = UserIncomingSMBarred & LFR = SMSC_ +PR_LC_SMSC_Encoding_Error) | RcdTyp = DelRecpt)', + 'total' => 'false' + } }, { +'2' => { + 'colName' => 'Ex-Col3', + 'formula' => '(RcdTyp = DelAck + OrigInf = SMPP)', + 'total' => 'false' ..... and continues

In want to replace the formula in a foreach loop. But cant able to access. Thanks for the help

my %doc = %{ $doc }; foreach my $sheet (keys %{ $doc{'_source'}{'sheets'} }) { foreach my $columns (@{ $doc{'_source'}{'sheets'}{$sheet}{'formula +tes'} }) { my %columns = %{ $columns }; foreach my $one (keys %{ $columns }) { #print $doc{'_source'}{'sheets'}{$sheet}{'formulates'}{$co +lumns}->{$one}{'formula'},$/; #print $doc{'_source'}{'sheets'}{$sheet}{'form +ulates'}{$columns}{$one}{'formula'},$/; ### I want to replace the formula variable her +e### } } }

Replies are listed 'Best First'.
Re: Return value of Search::Elasticsearch search query
by Athanasius (Archbishop) on Jul 09, 2016 at 04:42 UTC

    Hello ravi45722,

    Since $columns is already a (hash) reference, you can use it directly:

    #! perl use strict; use warnings; use Data::Dump; my $doc = { _source => { sheets => { sheet1 => { Sheet_Name => 'Ex-Sheet', formulates => [ { 0 => { colName => 'Ex-Col1', formula => '((DelvSts = Deleted + RcdTyp = + DelAck) & RcdTyp = DelRecpt)', total => 'false' }, }, { 1 => { colName => 'Ex-col2', formula => '((DelvSts = UserIncomingSMBarr +ed & LFR = SMSC_PR_LC_SMSC_Encoding_Error) | RcdTyp = DelRecpt)', total => 'false' }, }, { 2 => { colName => 'Ex-Col3', formula => '(RcdTyp = DelAck + OrigInf = S +MPP)', total => 'false' }, }, ], }, }, }, }; print "BEFORE:\n"; dd $doc; print '-' x 30, "\n"; my @new_formulae = qw( abc mno xyz ); for my $sheet (keys %{ $doc->{_source}{sheets} }) { for my $columns (@{ $doc->{_source}{sheets}{$sheet}{formulates} }) { for my $one (keys %{ $columns }) { # print $columns->{$one}{formula}, $/; $columns->{$one}{formula} = shift @new_formulae; } } } print "AFTER:\n"; dd $doc; print '-' x 30, "\n";

    Output:

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Return value of Search::Elasticsearch search query
by Laurent_R (Canon) on Jul 09, 2016 at 09:00 UTC
    I thinlk that this:
    foreach my $sheet (keys %{ $doc{'_source'}{'sheets'} }) { foreach my $columns (@{ $doc{'_source'}{'sheets'}{$sheet}{'formula +tes'} }) { # ...
    is uselessly complicated.

    If you use the values function instead of the keys function, you don't have to dereference the whole structure several times.

    For example, re-using the $doc variable definition provided by Athanasius, you could access the formulas this way:

    for my $sheet (values %{ $doc->{_source}{sheets} }) { for my $columns ( values %{$sheet} ) { for my $one ( @{ $columns }) { print "$_->{formula} \n" for values %{$one}; } } }
    Which prints out:
    ((DelvSts = Deleted + RcdTyp = DelAck) & RcdTyp = DelRecpt) ((DelvSts = UserIncomingSMBarred & LFR = SMSC_PR_LC_SMSC_Encoding_Erro +r) | RcdTyp = DelRecpt) (RcdTyp = DelAck + OrigInf = SMPP)
    HTH.

      Very nice. Tq But I got another problem. After changing the values in the hash I tried to insert the doc into ES again. But its showing below mentioned error.

      [Request] ** [http://172.16.15.153:9200]-[400] [mapper_parsing_excepti +on] failed to parse, called from sub Search::Elasticsearch::Role::Cli +ent::Direct::__ANON__ at ./complex_regex_bkp.pl line 93. With vars: { +'body' => {'status' => 400,'error' => {'root_cause' => [{'reason' => +'failed to parse','type' => 'mapper_parsing_exception'}],'reason' => +'failed to parse','type' => 'mapper_parsing_exception','caused_by' => + {'reason' => 'Mixing up field types: class org.elasticsearch.index.m +apper.core.StringFieldMapper$StringFieldType != class org.elasticsear +ch.index.mapper.internal.IndexFieldMapper$IndexFieldType on field _in +dex','type' => 'illegal_state_exception'}}},'request' => {'serialize' + => 'std','path' => '/my_app/blog_post/1','ignore' => [],'mime_type' +=> 'application/json','body' => {'_source' => {'sheets' => {'sheet1' +=> {'Sheet_Name' => 'Ex-Sheet','forumle' => [{'1' => {'colName' => 'E +x-Col1','formula' => '{"query":{"constant_score":{"filter":{"bool":{" +should":[{"bool":{"must":[{"term":{"column08":"Submit"}},{"term":{"co +lumn10":"Delivered"}},{"term":{"column09":"Something"}}]}},{"bool":{" +must":[{"term":{"column08":"Delivered"}},{"term":{"column09":"Somethi +ng"}}]}}]}}}}}','total' => 'false'},'0' => {'colName' => 'Ex-Col1','f +ormula' => '{"query":{"constant_score":{"filter":{"bool":{"should":[{ +"bool":{"must":[{"term":{"column08":"Submit"}},{"term":{"column10":"D +elivered"}},{"term":{"column09":"Something"}}]}},{"bool":{"must":[{"t +erm":{"column08":"Delivered"}},{"term":{"column09":"Something"}}]}},{ +"bool":{"must":[{"term":{"column08":"Submit"}},{"term":{"column10":"D +elivered"}},{"term":{"column09":"Something"}}]}},{"bool":{"must":[{"t +erm":{"column08":"Delivered"}},{"term":{"column09":"Something"}}]}}]} +}}}}','total' => 'false'},'2' => {'colName' => 'Ex-Col1','formula' => + '{"query":{"constant_score":{"filter":{"bool":{"must":[{"term":{"col +umn08":"Submit"}},{"term":{"column10":"Delivered"}},{"term":{"column0 +9":"Something"}}]}}}}}','total' => 'false'}}]}}},'_index' => 'testing +','_id' => '2','_type' => 'mytype','found' => bless( do{\(my $o = 1)} +, 'JSON::XS::Boolean' ),'_version' => 20},'qs' => {},'method' => 'POS +T'},'status_code' => 400}

      I know the elastic search needs JSON data as a body. So I tried to convert this into JSON.

      #my $temp = bless $doc; #my $json = encode_json \%temp;

      Then the data is updated without error but the data in DB is like "_source": {"main:HASH(0x25d3100)}". Any help on inserting the data back again

        Please read the error message:

        'reason' => 'failed to parse','type' => 'mapper_parsing_exception','ca +used_by' => {'reason' => 'Mixing up field types: class org.elasticsea +rch.index.mapper.core.StringFieldMapper$StringFieldType != class org. +elasticsearch.index.mapper.internal.IndexFieldMapper$IndexFieldType o +n field _index','type' => 'illegal_state_exception'}}}

        What you submit does not match what Elasticsearch expects for the string field. So you should lean what Elasticsearch expects and then submit the appropriate data types.

        You don't need to convert the Perl data structure to JSON yourself. The Search::Elasticsearch wrappers handle that for you.