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

#$condition = "((column08=Submit & column10=Delivered & column09=Somet +hing) | (column08=Delivered))"; $condition = "(column08=Submit & column10=Delivered & column09=Somethi +ng)"; #$condition = "((column08=Submit & column10=Delivered & column09=Somet +hing) | (column08=Delivered & column09=Something))";

Hope you have idea on elastic search. From the GUI i will get these type of conditions. I have to parse this into elastic search queries. Is there any easiest way to do this.

Example : { 'query' => { 'constant_score' => { 'filter' => { 'bool' => { + 'must' => [ + { + 'term' => { + 'column08' => 'Submit' + } + }, + { + 'term' => { + 'column10' => 'Delivered' + } + }, + { + 'term' => { + 'column09' => 'Something' + } + } + ] } } } } }

Any help will be appreciated.

Upto now I tried this. But missing some where

#!/usr/bin/perl #use strict; #use warnings; use Data::Dumper; use List::MoreUtils qw(any uniq); use JSON; $condition = "((column08=Submit & column10=Delivered & column09=Someth +ing) | (column08=Delivered))"; #$condition = "(column08=Submit & column10=Delivered & column09=Someth +ing)"; #$condition = "((column08=Submit & column10=Delivered & column09=Somet +hing) | (column08=Delivered & column09=Something))"; my $char_index = -1; my $stack = 0; my @condition_array = (); sub parse_function { $start_pos = $_[0]; $end_pos = ($_[1]); my @return_array = (); my $end_pos = ($end_pos - $start_pos)+1; my $string = substr($condition,$start_pos,$end_pos); print $string,$/; if (($string =~ m/(=|!=)/)) { my @matches = grep defined, split / ([|&]) /, $string; if ((scalar @matches) > 1) { foreach my $one (@matches) { if (($one =~ tr/=//) == 1) { my ($key,$value)=(split /=/,$one); push @return_array, { term => { $key => $value} }; } elsif (($one =~ tr/!=//) == 1) { my ($key,$value)=(split /!=/,$one); push @return_array, { term => { $key => $value} }; } else { push (@symbol_array,$one); } } @symbol_array = uniq (@symbol_array); $symbol_count = scalar @symbol_array; if ($symbol_count > 1) { print "Check the condition once again... Getting multi + symbol in one brace"; exit; } if (@symbol_array[0] == '&') { $return_hash{'bool'}{'must'} = [@return_array]; } elsif (@symbol_array[0] == '|') { $return_hash{'bool'}{'should'} = [@return_array]; } push @condition_array, %return_hash; print Dumper \@condition_array; exit; $count = @condition_array; return $count; } else { my ($key,$value)=(split /=/,$string); push @condition_array, { term => { $key => $value} }; $count = @condition_array; return $count; } } else { #print "In final else loop"; my @matches = grep defined, split / ([|&]) /, $string; foreach my $one (@matches) { if ($one == '&' or $one == '|') { push (@array_symbol,$one); } else { push (@return_array,$one); } } @array_symbol = uniq (@array_symbol); $count_array_symbol = @array_symbol; if ($count_array_symbol > 1) { print "In final loop : Got two different operators"; exit; } else { if ($array_symbol[0] == '|') { foreach my $instance (@return_array) { $return_hash{'bool'}{'should'} = [@condition_array +[int($instance)]]; } } if ($array_symbol[0] == '&') { foreach my $instance (@return_array) { $return_hash{'bool'}{'match'} = [@condition_array[ +int($instance)]]; } } push @condition_array, \%return_hash; print Dumper \%return_hash; $count = @condition_array; return $count; } } } HERE: $char_index = -1; foreach my $char (split //, $condition) { $char_index++; if ( (index($condition,'(') != -1)) { if ($char eq "(") { $open_brace_index = $char_index; } elsif ($char eq ")") { $returned = parse_function(($open_brace_index+1),($char_in +dex-1)); $first_string = substr($condition,0,$open_brace_index); $last_string = substr($condition,($char_index+1),(length($ +condition)-$char_index)); #print $last_string,$/; $condition = $first_string.$returned.$last_string; print $condition,$/; goto HERE; } } else { $main_hash{"query"}{"constant_score"}{"filter"} = @condition_a +rray[(int($condition)-1)]; my $json = encode_json \%main_hash; print $json; print Dumper \%main_hash; #print "In this loop"; } } exit;

Replies are listed 'Best First'.
Re: Queries for elastic search using perl
by Corion (Patriarch) on Jun 28, 2016 at 14:29 UTC

    What do you mean by "But missing some where"?

    Also note that there is Search::Elasticsearch, which is a module geared towards talking to Elasticsearch.

      I know the module. But I am preparing the queries for the elastic search.

       ((column08=Submit & column10=Delivered & column09=Something) | (column08=Delivered))

      This is the condition I am getting from GUI. I have to query the elastic search and return the result to the GUI through perl. For Quering we need to parse the condition in the form of elastic search query.

      Whats my problem here is in my code (Mentioned in the main thread) 1) I am passing the inner braces to the function first

       column08=Submit & column10=Delivered & column09=Something

      2) In line 58 I am giving my array to a hash

       $return_hash{'bool'}{'must'} = [@return_array];

      I expected the output as

      $VAR1 = ['bool' => { 'must' => [ { 'term' => { 'column08' => 'Submit' } }, { 'term' => { 'column10' => 'Delivered' } }, { 'term' => { 'column09' => 'Something' } } ] } ]

      But Its returning it as

      $VAR1 = [ 'bool', { 'must' => [ { 'term' => { 'column08' => 'Submit' } }, { 'term' => { 'column10' => 'Delivered' } }, { 'term' => { 'column09' => 'Something' } } ] } ];

        Where do the two data structures differ?

Re: Queries for elastic search using perl
by choroba (Cardinal) on Jun 28, 2016 at 16:19 UTC
    If you want to parse bracketed boolean expressions, write a proper parser. For example, using Marpa::R2:
    #! /usr/bin/perl use warnings; use strict; use Data::Dumper; use Marpa::R2; my $dsl = << '__DSL__'; :default ::= action => [values] lexeme default = latm => 1 Expression ::= ('(') Expression (')') action => ::first | Assignment action => ::first | Expression ' & ' Expression | Expression ' | ' Expression Assignment ::= key '=' value key ~ [\w]+ value ~ [\w]+ __DSL__ my $grammar = 'Marpa::R2::Scanless::G'->new({ source => \$dsl }); for my $condition ( '(column08=Submit & column10=Delivered & column09= +Something)', '((column08=Submit & column10=Delivered & column09 +=Something) | (column08=Delivered))', '((column08=Submit & column10=Delivered & column09 +=Something) | (column08=Delivered & column09=Something))', ) { print $condition, "\n"; my $parser = 'Marpa::R2::Scanless::R'->new({ grammar => $grammar +}); $parser->read(\$condition); print Dumper $parser->value; }

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

      Its not a boolean expression its just an indication for what we have to do in elastic search.  (column08=Submit & column10=Delivered & column09=Something) If this is the condition I am passing to a function I need output as

      { 'bool'=> { 'must'=> [ { 'term'=> {'column08'=> 'Submit'}}, { 'term'=> {'column10' => 'Delivered'}}, { 'term'=> {'column09' => 'Something'} ] } }
       (column08=Submit | column10=Delivered | column09=Something)
      { 'bool'=> { 'should'=> [ { 'term'=> {'column08'=> 'Submit'}}, { 'term'=> {'column10' => 'Delivered'}}, { 'term'=> {'column09' => 'Something'} ] } }

      Can you help me in this how to do ???