当前位置: 首页 > 知识库问答 >
问题:

ElasticSearch无痛脚本:无法使用脚本分数访问嵌套对象

公良理
2023-03-14

我想从特定字段中搜索关键字并返回文档。在这些文档之上,我希望遍历每个嵌套对象,并从选定文档的同一特定字段中再次搜索关键字。

如果关键字存在,则检查:如果布尔isCurrent = True,则设置isCurrent=0,并将该值追加到列表中;否则,如果isCurrent = False,则取当前日期时间的差值,结束日期时间,并获得以月为单位的值,并将该值追加到列表中。

最后,从每个文档的列表中获取最小值,并根据最小值对文档进行排序。

我可以通过script_fields进行自定义登录,并根据最小值对文档进行排序。当我在script_score中使用相同的登录时,它不起作用。当我调试时,我看到使用参数访问嵌套字段时出现问题。_source。

任何帮助将不胜感激。

请使用script_fields查找以下弹性搜索查询。在这里,我从python脚本传递current_millizes值。

    query = {
        'query': {
            "nested": {
                "path": "person.experiences",
                "query": {
                    "query_string": {
                        "query": keywords,
                        "fields": ["person.experiences.description"],
                        "default_operator": "AND"
                    }
                }
            }
        },
        "script_fields": {
            "recency": {
                "script": {
                    "lang": "painless",
                    "inline": """
                            def myString = "";
                            def isCurrent = 0;
                            def isFound = false;
                            def index_position = 0;
                            def recency_num = 0;
                            def result = 0;
                            def list = new ArrayList();

                            // for loop starts here
                            for(int i=0; i<params._source.person.experiences.size(); i++){
                            myString = params._source.person.experiences[i].description;

                            // string match starts here
                            if(myString != null && myString != ''){
                            def matcher1 = /electric/.matcher(myString.toLowerCase());
                            def matcher2 = /vehicle/.matcher(myString.toLowerCase());                    
                            //if(wordMatcher.find()){
                            if (matcher1.find() || matcher2.find()){
                            isFound = true;
                            }

                            if (isFound == true){
                            // recency check starts here
                            isCurrent = params._source.person.experiences[i].isCurrent;
                            if(isCurrent == true){
                            isCurrent=0;
                            result+=isCurrent;
                            list.add(isCurrent);
                            } else{
                            ZonedDateTime now = ZonedDateTime.ofInstant(Instant.ofEpochMilli(params['current_datetime']), ZoneId.of('Z'));
                            ZonedDateTime end_date = ZonedDateTime.parse(params._source.person.experiences[i].end);
                            isCurrent = end_date.until(now, ChronoUnit.MONTHS);
                            list.add(isCurrent);
                            result+=isCurrent;
                            recency_num = isCurrent;
                            }
                            }

                            }
                            }
                            def min = list.get(0);
                            for (int i : list){
                            min = min < i ? min : i;
                            }
                            return min;
                            """,
                    "params": {
                        "search_keywords": "Machine Learning",
                        "current_datetime": current_milliseconds
                    }

                }
            }
        }
    }

提前感谢。

共有1个答案

穆劲
2023-03-14

在您的情况下,有效的<code>script_score

GET my-index/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "function_score": {
            "functions": [
              {
                "script_score": {
                  "script": {
                    "source": """
                      def myString = "";
                      def isCurrent = 0;
                      def isFound = false;
                      def index_position = 0;
                      def recency_num = 0;
                      def result = 0;
                      def list = new ArrayList();
          
                      def experiences = params._source.person.experiences;
          
                      // for loop starts here
                      for (int i=0; i<experiences.length; i++){
                        def experience = experiences[i];
                        
                        myString = experience.description;
            
                        // string match starts here
                        if(myString != null && myString != '') {
                          def matcher1 = /electric/.matcher(myString.toLowerCase());
                          def matcher2 = /vehicle/.matcher(myString.toLowerCase());                    
                          
                          if (matcher1.find() || matcher2.find()){
                            isFound = true;
                          }
            
                          if (isFound == true){
                            // recency check starts here
                            isCurrent = experience.isCurrent;
                        
                            if (isCurrent == true){
                              isCurrent=0;
                              result += isCurrent;
                              list.add(isCurrent);
                            } else {
                              def now = ZonedDateTime.ofInstant(Instant.ofEpochMilli(params['current_datetime']), ZoneId.of('Z'));
                              def end_date = ZonedDateTime.parse(experience.end);
                              isCurrent = end_date.until(now, ChronoUnit.MONTHS);
                              list.add(isCurrent);
                              result += isCurrent;
                              recency_num = isCurrent;
                            }
                          }
                        }
                      }
                      
                      if (list.length === 0) {
                        return 0;
                      }
                      
                      def min = list.get(0);
                      
                      for (int i : list){
                        min = min < i ? min : i;
                      }
                      
                      return min;
                    """,
                    "params": {
                        "search_keywords": "Machine Learning",
                        "current_datetime": 1643036066000
                    }
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}

请注意,正则表达式、迭代和(日期)分析的负载可以大大提高查询分辨率。

 类似资料:
  • 我没有Java经验,我对elasticsearch无痛脚本语言有问题。(这个名字叫“无痛”,选得不好)。 对于下面的代码,我得到了错误: 无法应用 [ 我用(float) doc['newPrice']将它绑定为float 然后我改为<code>“Double price=((Double)doc['discountPrice'] 并收到: “无法从[双]铸造到[双]。” 有人可以帮助我,尝试了很

  • 以下是我的查询的简化版本: 希望有办法解决这个... 提前感谢你的帮助

  • 问题内容: 我刚开始使用ES,但仍然喜欢交易的技巧!!!我需要替换/覆盖嵌套对象类型的字段之一。这是示例文档: 映射以上文档: 我需要更新给定ref_name的计数字段值。例如,在上述情况下,如果 ref_name 是“ test1 ”,我希望新 计数 为 500 。我想出了下面的简单 脚本 来更改 计 数值,它可以正常执行而没有任何错误,但是我看不到该值正在更新。 以下是响应: 但是,当我看到该

  • 我用ES 5.5的时候更新到6.7。无痛脚本不起作用 这是5.5如果我想获取嵌套文档[transFilter]我这样做 效果很好。 但是 当我使用6.7版本时 params['_source']['carFilter'] 我发现它不起作用 所有参数['_source']为空 我的映射 我的数据示例 和我的查询脚本示例 甚至没有错误只有事实 这一行已经返回 上面的简单无痛只是为了说明问题,下面附上了

  • 问题内容: 我在elasticsearch中的索引具有以下映射: 源文档如下: 我正在尝试使用距离脚本来基于地理点计算距离。我在elasticsearch结果中发现了该帖子的Return distance吗?帮我 我正在尝试获取所有结果,按半径1km进行过滤,获取距离,然后对geo_point进行排序。查询的结构如下: 我收到状态为500的以下错误: 我尝试以这种方式重写查询: 然后我得到这个错误

  • 问题内容: 我有一个存储在ElasticSearch中的文档,如下所示。_资源: 我可以使用脚本化的指标汇总 http://www.elasticsearch.org/guide/zh- CN/elasticsearch/reference/current/search-aggregations-metrics-scripted- metric- aggregation.html访问 文档中的字符