Использование вложенных значений в script_score - PullRequest
0 голосов
/ 16 апреля 2020

Я пытаюсь использовать вложенные значения в оценке скрипта, но у меня возникают проблемы с его работой, потому что я не могу перебрать поле, получив к нему доступ через do c. Кроме того, когда я пытаюсь запросить его в Кибане, например _type:images AND _exists_:colors, он не будет соответствовать ни одному документу, даже если это поле явно присутствует во всех моих документах, когда я просматриваю их по отдельности. Однако я могу получить к нему доступ с помощью params._source , но я прочитал, что он может быть медленным и медленным и не очень рекомендуется.

Я знаю, что эта проблема связана с как мы создали это вложенное поле, поэтому, если я не смогу найти что-то лучшее, чем это, мне придется переиндексировать наши документы 2m + и посмотреть, смогу ли я найти другой способ решения проблемы, но я бы хотел этого избежать, а также просто лучше понять, как Elasti c работает за кулисами, и почему он действует так, как здесь.

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

Запросы на создание индекса и документов с вложенным полем, содержащим массивы цветов с разбивкой по 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
      }
    ]
}

Теперь, если я выполню этот запрос, используйте do c:

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());
                  }
                }
              """
            }
          }
        }
      ]
    }
  }
}

Я получу исключение No field found for [colors] in mapping with types [], но если я вместо этого использую params._source , например:

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": "exception", "reason": "100"}, поэтому я знаю, что это сработало, поскольку первый документ красный и имеет значение 100.

Я даже не уверен, что это можно классифицировать как вопрос, но больше крик о помощи. Если кто-то может объяснить, почему это ведет себя так, как есть, и дать представление о наилучшем способе решения этой проблемы, я был бы очень признателен.

(Кроме того, некоторые советы по отладке в Безболезненно тоже было бы прекрасно !!!)

1 Ответ

0 голосов
/ 21 апреля 2020

Не беспокойтесь о медленности params._source - это ваш единственный выбор, потому что итерация вложенного контекста 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;
                    """
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}

Безболезненный контекст счета здесь .

Во-вторых, вы были довольно близки, создавая исключение вручную - - есть более чистый способ сделать это. Раскомментируйте Debug.explain(color);, и вы готовы к go.

Еще одна вещь, я намеренно добавил запрос match, чтобы увеличить баллы, но, что более важно, чтобы проиллюстрировать, как запрос построен в background - при повторном запуске выше в GET images/_validate/query?explain, вы сами убедитесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...