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

在script_score中使用嵌套值

麹繁
2023-03-14

我试图在脚本分数中使用嵌套值,但我在使它工作时遇到了问题,因为我无法通过doc访问它来迭代字段。此外,当我尝试在Kibana中像< code > _ type:images AND _ exists _:colors 一样查询它时,它不会匹配任何文档,即使当我单独查看所有文档时,该字段都清楚地出现在它们中。不过,我可以使用参数来访问它。_source,但是我看过可以慢一点慢一点,真的不推荐

我知道这个问题都是由于我们创建这个嵌套字段的方式,所以如果我不能想出比这个更好的方法,我将不得不重新索引我们的2m文档,看看是否可以找到解决这个问题的另一种方法,但我想避免这一点,同时也只是更好地理解Elastic在幕后的工作方式,以及它为什么会在这里这样做。

我将在这里提供的示例不是我的现实生活问题,但也描述了这个问题。假设我们有一个描述图像的文档。该文档有一个字段,其中包含图像中存在多少红色、蓝色和绿色的值。

请求创建索引和文档,其嵌套字段包含颜色数组,并在它们之间拆分 100 个点:

PUT images
{
  "settings": {
    "number_of_shards": 1
  },
  "mappings": {
    "_doc": {
      "properties": {
        "id" : { "type" : "integer" },
        "title" : { "type" : "text" },
        "description" : { "type" : "text" },
        "colors": {
          "type": "nested",
          "properties": {
            "red": {
              "type": "double"
            },
            "green": {
              "type": "double"
            },
            "blue": {
              "type": "double"
            }
          }
        }
      }
    }
  }
}

PUT images/_doc/1
{
    "id" : 1,
    "title" : "Red Image",
    "description" : "Description of Red Image",
    "colors": [
      {
        "red": 100
      },
      {
        "green": 0
      },
      {
        "blue": 0
      }
    ]
}

PUT images/_doc/2
{
    "id" : 2,
    "title" : "Green Image",
    "description" : "Description of Green Image",
    "colors": [
      {
        "red": 0
      },
      {
        "green": 100
      },
      {
        "blue": 0
      }
    ]
}

PUT images/_doc/3
{
    "id" : 3,
    "title" : "Blue Image",
    "description" : "Description of Blue Image",
    "colors": [
      {
        "red": 0
      },
      {
        "green": 0
      },
      {
        "blue": 100
      }
    ]
}

现在,如果我使用doc运行这个查询:

GET images/_search
{
  "query": {
    "function_score": {
      "functions": [
        {
          "script_score": {
            "script": {
              "source": """
                boolean debug = true;
                for(color in doc["colors"]) {
                  if (debug === true) {
                    throw new Exception(color["red"].toString());
                  }
                }
              """
            }
          }
        }
      ]
    }
  }
}

我将得到异常<code>在类型为〔〕

GET images/_search
{
  "query": {
    "function_score": {
      "functions": [
        {
          "script_score": {
            "script": {
              "source": """
                boolean debug = true;
                for(color in params._source["colors"]) {
                  if (debug === true) {
                    throw new Exception(color["red"].toString());
                  }
                }
              """
            }
          }
        }
      ]
    }
  }
}

我能够输出"caused_by":{"type":"异常","原因":"100"},所以我知道它起作用了,因为第一个文档是红色的,并且值为100。

我甚至不确定这能不能算作一个问题,而更像是一种求助。如果有人能解释为什么会这样,并给出一个解决这个问题的最佳方法,我会非常感激。

(此外,在无痛中调试的一些技巧也会很可爱!!!)

共有2个答案

程俊力
2023-03-14

不用担心< code>params速度慢。_source -这是唯一的选择,因为迭代< code>doc的嵌套上下文只允许访问一种嵌套颜色。

试试这个:

GET images/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "title": "image"
          }
        },
        {
          "function_score": {
            "functions": [
              {
                "script_score": {
                  "script": {
                    "source": """
                        def score = 0;
                        for (color in params._source["colors"]) {
                          // Debug.explain(color);
                          if (color.containsKey('red')) {
                            score += color['red'] ;
                          }
                        }
                        return score;
                    """
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}

无痛评分语境在此。

第二,您非常接近手动抛出异常——尽管有一种更干净的方法。取消注释<code>调试。解释(颜色) 然后你就可以走了。

还有一件事,我特意添加了一个匹配查询来增加分数,但更重要的是,为了说明如何在后台构建查询 - 当您在GET images/_validate/query?explain下重新运行上述内容时,您将亲眼看到。

容修贤
2023-03-14

在 Elasticsearch 的评分脚本“script_score”: {“script”: {“source”: “...” }}您可以使用param._source对象访问嵌套值。

例如,如果您有包含以下文档的文档索引:

{
  "title": "Yankees Potential Free Agent Target: Max Scherzer",
  "body": "...",
  "labels": {
    "genres": "news",
    "topics": ["sports", "celebrities"]
    "publisher": "CNN"
  }
}

以下查询将按随机顺序返回100个文档,优先选择带有<code>体育</code>主题的文档:

GET documents/_search
{
  "size": 100,
  "sort": [
    "_score"
  ],
  "query": {
    "function_score": {
      "query": { "match_all": {} },
      "functions": [
        {
          "random_score": {}
        },
        {
          "script_score": {
            "script": {
              "source": """
                double boost = 1.0;
                if (params._source['labels'] != null && params._source['labels']['topics'] != null && params._source['labels']['topics'].contains('sports') {
                    boost += 2.0;
                }
                return boost;
              """
            }
          }
        }
      ],
      "score_mode": "multiply",
      "boost_mode": "replace"
    }
  }
}
 类似资料:
  • 我被困在将嵌套JS与宇宙数据库核心SQL API集成上。我知道有一个用于 Cosmos DB 的模块(https://github.com/nestjs/azure-database),但我需要数据架构来支持嵌套的 json,如下所示: 我认为@nestjs/azure-database不支持这一点(或者我可能错了),因为当我检查他们的示例和quickstart时,没有这样的json模式的示例。

  • 我想在SpringBoot中使用quartz运行一个作业,其中多个线程将执行该方法。我想要的是将每次处理的结果都保存在redis中,这样我就可以知道这个工作有多好。 我想以这种形式保存redis中的数据。 我想插入关键日期中的所有项目。因为有多个线程在工作,所以每个线程都在处理某个项目。所以所有项目都应该只插入到键(日期)中。 可能吗? 一种解决方案是一次又一次地重写(date)键的数据,首先从r

  • 如何聚合一个值在嵌套在Elasticsearch嵌套位置?我对一个嵌套对象没有问题,但在嵌套对象内的嵌套我感到困惑... 样本数据: 欲望结果: 在索引映射中,我将cat_a和条目字段的类型设置为嵌套,当我从工具字段查询聚合时,在cat_a的根(级别1)中没有问题,并且可以工作,但是在聚合中在rx_a(这是在第2级)我不能检索结果,它或空或显示错误,因为我的错误查询。 查询级别1 agg: 如何处

  • 问题内容: 我需要在AngularJS 1.0.7中使用参数运行函数 “ searchBoats(boatType)” 。此参数是另一个函数 parseBoatType 的结果,该函数 正在运行使用$ resource调用API的服务 。当带有诺言的资源中返回boatType时,如何运行searchBoats? 这是我尝试的: 问题答案: 您可以从函数中的资源返回资源,并使用Promise来解决延

  • 我试图在嵌套对象中使用DynamoDB注释,如下所示: 我没有看到上面的属性是在UserAction类中自动生成的。我想知道嵌套对象中是否支持这些注释用法。请建议。

  • 我在下面的代码中使用了嵌套的for循环,并且我有一些条件来中断内部的for循环,这提高了代码的性能。 现在,如何使用 Java 8 流来执行相同的逻辑?我想出了下面的代码: 在这里,我不能在java流中使用< code>break语句,所以我使用了< code>return语句,但它仍然运行内部循环,因为它不会中断内部循环,所以性能没有提高。