如何为嵌套对象构建简单的术语查询?

How to build simple terms query for nested object?

我有这样的索引:

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"
    }
  ]
}

此查询 returns 0 个文档。

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

你能解释一下为什么吗?我认为它应该 return 文档,其中 location.slugremotenew-york.

Nested- Query 语法不同

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"
            }
          ]
        }
      }
    ]

它将 return 整个文档,其中 location.slug 匹配 "remote" 或 "new-york"。如果你想得到匹配的嵌套文档,你需要使用 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"
                  }
                }
              ]
            }
          }
        }
      }
    ]

我还看到您对不同类型的相同数据使用了两个字段。如果两个字段(名称和 slug)中的数据相同并且只有数据类型不同,则可以使用 fields 来表示

It is often useful to index the same field in different ways for different purposes. This is the purpose of multi-fields. For instance, a string field could be mapped as a text field for full-text search, and as a keyword field for sorting or aggregations:

在那种情况下,您的映射将变为下面

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"
      }
    }
  }
}