2017-01-13 3 views
0

На работе у меня есть сценарий, сделанный людьми, которых больше нет. Он используется для извлечения файла XML с таким узлом:Динамически модифицировать запрос ElasticSearch с использованием Perl

<query maxresults='15000'> 
     <![CDATA[                   
     and(                   
       isavailable:1,         
       not(designation:string("test wine", mode="or")),     
       visibility:10,             
       bestprice:>0               
     )                    
     ]]> 
    </query> 

Мы используем Perl для этого. Цель состоит в том, чтобы изменить запрос FAST, содержащийся внутри узла, для динамического добавления некоторых параметров (например, ограничить результаты с помощью атрибута maxresults). Эта часть кода работает, но мы переходим к ElasticSearch, и мне нужно изменить код, чтобы он работал.

Проблема в том, что я не могу найти надежный способ изменить запрос ElasticSearch с помощью Perl. До сих пор я сделал это:

use strict; 
use warnings; 
use JSON; 
use Data::Dumper; 
use Search::Elasticsearch; 

my $json = 
'{"query": 
    {"bool": 
     {"must": 
      [ 
      {"term": 
       {"isavailable":"1"} 
      }, 
      {"term": 
       {"visibility":"10"} 
      }, 
      {"range": 
       {"bestprice": 
        {"gt":"0"} 
       } 
      } 

      ], 
     "must_not": 
      [{"regexp": 
       {"designation":"[Tt]+[Ee]+[Ss]+[Tt]+"} 
      }, 
      {"regexp": 
       {"designation":"[Ww]+[Ii]+[Ne]+[Ee]+"} 
      } 
      ] 
     } 
    } 
}'; 

my $result = decode_json($json); 

Но это дает мне хэш вместо объекта, и я получаю головную боль пытается динамически изменять этот хэш только добавить (например):

{"regexp": {"designation":"[Ff]+[Oo]+"}} 

в массив внутри объекта «must_not».

Я пытался сделать это:

my %must = (must_not => [{"regexp" => 
             {"designation" => "[Ff]+[Oo]+"} 
          } 
          ]); 


$result{"query"} = \%must; 

print keys(%{$result{query}}); 

Но это просто заменяет содержимое всего узла с% должны хэшированием, и я не могу найти способ, чтобы правильно добавляемый его. Я попытался нажать хэш внутри массива, содержащегося в объекте must_not, но я получаю ошибки.

Я действительно озадачен этой ситуацией, тем более, что я не специалист по Perl, поэтому любая помощь более чем приветствуется!

Спасибо!

+0

Если вы конвертируете что-то из JSON, вы получаете простую структуру данных. По умолчанию в Perl нет объектов. Вам нужно изменить структуру данных, это правильно. Вы должны пойти полностью, или он будет заменен, это правильно. – simbabque

ответ

2

Это не объект, потому что Perl по умолчанию не работает с объектами. Если вы хотите объект, вам нужно иметь класс, а затем создать его экземпляр. Но decode_json не может этого сделать. Все, что он делает, это вернуть сложную структуру данных.

Чтобы добавить еще одну запись в массив ref, содержащий фильтры внутри этой структуры данных, вам нужно указать push. Для этого вам нужно разыменовать массив ref, потому что push не любит работать со ссылками. Perl выполнит правильные действия для вас со следующим синтаксисом.

# this dereferences the array ref for push 
# |          | 
push @{ $result->{query}->{bool}->{must_not} }, { # the { starts a new hash ref 
    "regexp" => { 
     "designation" => "[Ff]+[Oo]+", # we like trailing commas in Perl 
    }, 
}; 

Если у вас есть очень новый Perl (5.24), можно также использовать после починки deref синтаксис здесь, который является немного чище читать.

push $result->{query}->{bool}->{must_not}->@, { ... }; 
+1

Спасибо за вашу помощь, теперь я могу сделать именно то, что хочу, и вы предоставили очень четкое объяснение того, что я делаю неправильно! – SmashingQuasar

1

Вы можете напрямую работать с хеш-кодом decode_json. Например,

  1. получить ссылку на свой must_not массив

    my $mustNots = $result->{query}->{bool}->{must_not}; 
    
  2. добавить фильтр к этому массиву, нажав хэш реф

    push(@{$mustNots}, {"regexp" => {"designation" => "[Ff]+[Oo]+"}}); 
    
  3. теперь есть третий вход в must_not, print encode_json($result); дает

    { 
        "query": { 
         "bool": { 
          "must": [ 
           { 
            "term": {"isavailable": "1"} 
           }, 
           { 
            "term": {"visibility": "10"} 
           }, 
           { 
            "range": {"bestprice": {"gt": "0"}} 
           } 
          ], 
          "must_not": [ 
           { 
            "regexp": { 
             "designation": "[Tt]+[Ee]+[Ss]+[Tt]+" 
            } 
           }, 
           { 
            "regexp": { 
             "designation": "[Ww]+[Ii]+[Ne]+[Ee]+" 
            } 
           }, 
           { 
            "regexp": { 
             "designation": "[Ff]+[Oo]+" 
            } 
           } 
          ] 
         } 
        } 
    } 
    
+0

Спасибо за вашу помощь, объединив ваш ответ на ответ @simbabque, теперь я понимаю, в чем была моя проблема! – SmashingQuasar

Смежные вопросы