使用Perl动态修改ElasticSearch查询

时间:2017-01-13 10:27:49

标签: perl elasticsearch

在工作中,我有一个由不再存在的人制作的脚本。它用于检索具有如下节点的XML文件:

 <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 hash替换整个节点内容,我找不到正确附加它的方法。我试图在must_not对象中包含的数组中推送一个哈希,但我只得到错误。

我对这种情况感到很困惑,特别是因为我不是真正的Perl专家,所以任何帮助都非常受欢迎!

谢谢!

2 个答案:

答案 0 :(得分:2)

它不是一个对象,因为Perl默认不使用对象。如果你想要一个对象,你需要有一个类,然后实例化它。但decode_json不能这样做。它只是返回一个复杂的数据结构。

要向包含该数据结构内部过滤器的数组引用添加另一个条目,您需要push它。为此,您需要取消引用数组引用,因为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),你也可以在这里使用post-fix deref语法,这个语法有点清晰。

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

答案 1 :(得分: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]+"
                        }
                    }
                ]
            }
        }
    }