Как построить простой запрос терминов для вложенного объекта? - PullRequest
0 голосов
/ 09 апреля 2020

У меня есть такой индекс:

PUT job_offers
{
  "mappings": {
    "properties": {
      "location": {
        "properties": {
          "slug": {
            "type": "keyword"
          },
          "name": {
            "type": "text"
          }
        },
        "type": "nested"
      },
      "experience": {
        "properties": {
          "slug": {
            "type": "keyword"
          },
          "name": {
            "type": "text"
          }
        },
        "type": "nested"
      }
    }
  }
}

Я вставляю этот объект:

POST job_offers/_doc
{
  "title": "Junior Ruby on Rails Developer",
  "location": [
    {
      "slug": "new-york",
      "name": "New York"
    },
    {
      "slug": "atlanta",
      "name": "Atlanta"
    },
    {
      "slug": "remote",
      "name": "Remote"
    }
  ],
  "experience": [
    {
      "slug": "junior",
      "name": "Junior"
    }
  ]
}

Этот запрос возвращает 0 документов.

GET job_offers/_search
{
  "query": {
    "terms": {
      "location.slug": [
        "remote",
        "new-york"
      ]
    }
  }
}

Можете ли вы объяснить мне почему? Я думал, что он должен вернуть документы, где location.slug это remote или new-york.

1 Ответ

1 голос
/ 09 апреля 2020

Nested - запрос имеет другой синтаксис

GET job_offers/_search
{
  "query": {
    "nested": {
      "path": "location",
      "query": {
        "terms": {
          "location.slug": ["remote","new-york"]
        }
      }
    }
  }
}

Результат:

  "hits" : [
      {
        "_index" : "job_offers",
        "_type" : "_doc",
        "_id" : "wWjoXnEBs0rCGpYsvUf4",
        "_score" : 1.0,
        "_source" : {
          "title" : "Junior Ruby on Rails Developer",
          "location" : [
            {
              "slug" : "new-york",
              "name" : "New York"
            },
            {
              "slug" : "atlanta",
              "name" : "Atlanta"
            },
            {
              "slug" : "remote",
              "name" : "Remote"
            }
          ],
          "experience" : [
            {
              "slug" : "junior",
              "name" : "Junior"
            }
          ]
        }
      }
    ]

Будет возвращен весь документ, где location.slug соответствует «remote» или "Нью-Йорк". Если вы хотите получить совпавший вложенный документ, вам нужно использовать inner_hits

GET job_offers/_search
{
  "query": {
    "nested": {
      "path": "location",
      "query": {
        "terms": {
          "location.slug": ["remote","new-york"]
        }
      },
      "inner_hits": {} --> note
    }
  }
}

Результат:

"hits" : [
      {
        "_index" : "job_offers",
        "_type" : "_doc",
        "_id" : "wWjoXnEBs0rCGpYsvUf4",
        "_score" : 1.0,
        "_source" : {
          "title" : "Junior Ruby on Rails Developer",
          "location" : [
            {
              "slug" : "new-york",
              "name" : "New York"
            },
            {
              "slug" : "atlanta",
              "name" : "Atlanta"
            },
            {
              "slug" : "remote",
              "name" : "Remote"
            }
          ],
          "experience" : [
            {
              "slug" : "junior",
              "name" : "Junior"
            }
          ]
        },
        "inner_hits" : {  --> will give matched nested object
          "location" : {
            "hits" : {
              "total" : {
                "value" : 2,
                "relation" : "eq"
              },
              "max_score" : 1.0,
              "hits" : [
                {
                  "_index" : "job_offers",
                  "_type" : "_doc",
                  "_id" : "wWjoXnEBs0rCGpYsvUf4",
                  "_nested" : {
                    "field" : "location",
                    "offset" : 0
                  },
                  "_score" : 1.0,
                  "_source" : {
                    "slug" : "new-york",
                    "name" : "New York"
                  }
                },
                {
                  "_index" : "job_offers",
                  "_type" : "_doc",
                  "_id" : "wWjoXnEBs0rCGpYsvUf4",
                  "_nested" : {
                    "field" : "location",
                    "offset" : 2
                  },
                  "_score" : 1.0,
                  "_source" : {
                    "slug" : "remote",
                    "name" : "Remote"
                  }
                }
              ]
            }
          }
        }
      }
    ]

Также я вижу, что вы используете два поля для одних и тех же данных с разными типами. если данные одинаковы в обоих полях (имя и фрагмент) и отличается только тип данных, для этого можно использовать поля

Часто бывает полезно проиндексировать одно и то же поле в разные способы для разных целей. Это цель мультиполя. Например, строковое поле может быть отображено как текстовое поле для полнотекстового поиска и как поле ключевого слова для сортировки или агрегирования:

В этом случае ваше отображение станет ниже

PUT job_offers
{
  "mappings": {
    "properties": {
      "location": {
        "properties": {
          "name": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword"
              }
            }
          }
        },
        "type": "nested"
      },
      "experience": {
        "properties": {
          "name": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword"
              }
            }
          }
        },
        "type": "nested"
      }
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...