2017-01-13 19 views
0

在工作中動態地修改ElasticSearch查詢我的人誰不存在任何更多的做了一個腳本。它用於檢索具有如下節點的XML文件:使用Perl

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

我們正在使用Perl進行此操作。我們的目標是修改包含動態地添加一些參數的節點內的FAST請求(例如限制與「的maxResults」屬性的結果)。在這部分代碼的工作,但我們切換到ElasticSearch,我需要更改代碼,以便它的工作原理。

問題是,我找不到用Perl修改ElasticSearch查詢的可靠方法。到目前爲止,我這樣做:

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_notprint 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