Условная исходная фильтрация вложенных объектов в ответах эластичного поиска - PullRequest
0 голосов
/ 18 марта 2019

У меня есть индекс документов со следующей (упрощенной) структурой.

{
  "product_id": "abc123",
  "properties": [
    {
      "key": "width",
      "value": 1000
    },
    {
      "key": "height",
      "value": 2000
    },
    {
      "key": "depth",
      "value": 500
    }
  ]
}

Каждый документ может иметь сотни свойств.

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

Получить все документы, соответствующие запросу x, и заполнить каждый документ свойствами ["height", "width", "foobar"].

Массив со свойствами, которые я хочу вернуть, создается во время запроса на основе ввода от пользователя.Документ в ответе на запрос будет выглядеть так:

{
  "product_id": "abc123",
  "properties": [
    {
      "key": "width",
      "value": 1000
    },
    {
      "key": "height",
      "value": 2000
    }
    // No depth!
  ]
}

Я пытался добиться этого с помощью фильтрации исходного кода, но безрезультатно.Я подозреваю, что поля сценария могут быть единственным способом решения этой проблемы, но я бы предпочел использовать какой-то стандартный способ.У кого-нибудь есть идеи?

1 Ответ

1 голос
/ 18 марта 2019

Лучшее, что я могу придумать, это использовать inner_hits.Например:

PUT proptest
{
  "mappings": {
    "default": {
      "properties": {
        "product_id": {
          "type": "keyword"
        },
        "color": {
          "type": "keyword"
        },
        "props": {
          "type": "nested"
        }
      }
    }
  }
}

PUT proptest/default/1
{
  "product_id": "abc123",
  "color": "red",
  "props": [
    {
      "key": "width",
      "value": 1000
    },
    {
      "key": "height",
      "value": 2000
    },
    {
      "key": "depth",
      "value": 500
    }
  ]
}
PUT proptest/default/2
{
  "product_id": "def",
  "color": "red",
  "props": [
  ]
}
PUT proptest/default/3
{
  "product_id": "ghi",
  "color": "blue",
  "props": [
    {
      "key": "width",
      "value": 1000
    },
    {
      "key": "height",
      "value": 2000
    },
    {
      "key": "depth",
      "value": 500
    }
  ]
}

Теперь мы можем запросить по color и получить только свойства height, depth и foobar:

GET proptest/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "color": {
              "value": "red"
            }
          }
        },
        {
          "bool": {
            "should": [
              {
                "nested": {
                  "path": "props",
                  "query": {
                    "match": {
                      "props.key": "height depth foobar"
                    }
                  },
                  "inner_hits": {}
                }
              },
              {
                "match_all": {}
              }
            ]
          }
        }

      ]
    }
  },
 "_source": {
   "excludes": "props"
 }
} 

Вывод

{
  "hits": {
    "total": 2,
    "max_score": 2.2685113,
    "hits": [
      {
        "_index": "proptest",
        "_type": "default",
        "_id": "1",
        "_score": 2.2685113,
        "_source": {
          "color": "red",
          "product_id": "abc123"
        },
        "inner_hits": {
          "props": {
            "hits": {
              "total": 2,
              "max_score": 0.9808292,
              "hits": [
                {
                  "_index": "proptest",
                  "_type": "default",
                  "_id": "1",
                  "_nested": {
                    "field": "props",
                    "offset": 2
                  },
                  "_score": 0.9808292,
                  "_source": {
                    "key": "depth",
                    "value": 500
                  }
                },
                {
                  "_index": "proptest",
                  "_type": "default",
                  "_id": "1",
                  "_nested": {
                    "field": "props",
                    "offset": 1
                  },
                  "_score": 0.9808292,
                  "_source": {
                    "key": "height",
                    "value": 2000
                  }
                }
              ]
            }
          }
        }
      },
      {
        "_index": "proptest",
        "_type": "default",
        "_id": "2",
        "_score": 1.287682,
        "_source": {
          "color": "red",
          "product_id": "def"
        },
        "inner_hits": {
          "props": {
            "hits": {
              "total": 0,
              "max_score": null,
              "hits": []
            }
          }
        }
      }
    ]
  }
}

Обратите внимание, что результаты содержат оба продукта abc123 и def с отфильтрованными правильными свойствами.Продукт abc123 частично соответствует данному списку свойств, def не содержит ни одного из них.Основные результаты определяются только внешним запросом color:red

Недостатком метода является то, что свойства не будут найдены под тем же верхним уровнем _source, но под ключом внутренних попаданий.

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