fields编辑

通常,以不同的方式索引同一个字段以用于不同的目的非常有用。这就是多字段的用途。例如,一个string字段可以映射为一个text字段用于全文搜索,以及一个keyword字段用于排序或聚合

resp = client.indices.create(
    index="my-index-000001",
    body={
        "mappings": {
            "properties": {
                "city": {
                    "type": "text",
                    "fields": {"raw": {"type": "keyword"}},
                }
            }
        }
    },
)
print(resp)

resp = client.index(
    index="my-index-000001",
    id="1",
    body={"city": "New York"},
)
print(resp)

resp = client.index(
    index="my-index-000001",
    id="2",
    body={"city": "York"},
)
print(resp)

resp = client.search(
    index="my-index-000001",
    body={
        "query": {"match": {"city": "york"}},
        "sort": {"city.raw": "asc"},
        "aggs": {"Cities": {"terms": {"field": "city.raw"}}},
    },
)
print(resp)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      properties: {
        city: {
          type: 'text',
          fields: {
            raw: {
              type: 'keyword'
            }
          }
        }
      }
    }
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 1,
  body: {
    city: 'New York'
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 2,
  body: {
    city: 'York'
  }
)
puts response

response = client.search(
  index: 'my-index-000001',
  body: {
    query: {
      match: {
        city: 'york'
      }
    },
    sort: {
      'city.raw' => 'asc'
    },
    aggregations: {
      "Cities": {
        terms: {
          field: 'city.raw'
        }
      }
    }
  }
)
puts response
{
	res, err := es.Indices.Create(
		"my-index-000001",
		es.Indices.Create.WithBody(strings.NewReader(`{
	  "mappings": {
	    "properties": {
	      "city": {
	        "type": "text",
	        "fields": {
	          "raw": {
	            "type": "keyword"
	          }
	        }
	      }
	    }
	  }
	}`)),
	)
	fmt.Println(res, err)
}

{
	res, err := es.Index(
		"my-index-000001",
		strings.NewReader(`{
	  "city": "New York"
	}`),
		es.Index.WithDocumentID("1"),
		es.Index.WithPretty(),
	)
	fmt.Println(res, err)
}

{
	res, err := es.Index(
		"my-index-000001",
		strings.NewReader(`{
	  "city": "York"
	}`),
		es.Index.WithDocumentID("2"),
		es.Index.WithPretty(),
	)
	fmt.Println(res, err)
}

{
	res, err := es.Search(
		es.Search.WithIndex("my-index-000001"),
		es.Search.WithBody(strings.NewReader(`{
	  "query": {
	    "match": {
	      "city": "york"
	    }
	  },
	  "sort": {
	    "city.raw": "asc"
	  },
	  "aggs": {
	    "Cities": {
	      "terms": {
	        "field": "city.raw"
	      }
	    }
	  }
	}`)),
		es.Search.WithPretty(),
	)
	fmt.Println(res, err)
}
PUT my-index-000001
{
  "mappings": {
    "properties": {
      "city": {
        "type": "text",
        "fields": {
          "raw": { 
            "type":  "keyword"
          }
        }
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "city": "New York"
}

PUT my-index-000001/_doc/2
{
  "city": "York"
}

GET my-index-000001/_search
{
  "query": {
    "match": {
      "city": "york" 
    }
  },
  "sort": {
    "city.raw": "asc" 
  },
  "aggs": {
    "Cities": {
      "terms": {
        "field": "city.raw" 
      }
    }
  }
}

city.raw字段是city字段的keyword版本。

city字段可用于全文搜索。

city.raw字段可用于排序和聚合

您可以使用更新映射 API将多字段添加到现有字段。

如果索引(或数据流)在您添加多字段时包含文档,则这些文档将不会具有新多字段的值。您可以使用更新查询 API填充新多字段。

多字段映射与父字段的映射完全独立。多字段不会从其父字段继承任何映射选项。多字段不会更改原始的_source字段。

具有多个分析器的多字段编辑

多字段的另一个用例是以不同的方式分析同一个字段以获得更好的相关性。例如,我们可以使用standard分析器(它将文本分解为单词)和english分析器(它将单词词干还原为其词根形式)来索引字段

resp = client.indices.create(
    index="my-index-000001",
    body={
        "mappings": {
            "properties": {
                "text": {
                    "type": "text",
                    "fields": {
                        "english": {"type": "text", "analyzer": "english"}
                    },
                }
            }
        }
    },
)
print(resp)

resp = client.index(
    index="my-index-000001",
    id="1",
    body={"text": "quick brown fox"},
)
print(resp)

resp = client.index(
    index="my-index-000001",
    id="2",
    body={"text": "quick brown foxes"},
)
print(resp)

resp = client.search(
    index="my-index-000001",
    body={
        "query": {
            "multi_match": {
                "query": "quick brown foxes",
                "fields": ["text", "text.english"],
                "type": "most_fields",
            }
        }
    },
)
print(resp)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      properties: {
        text: {
          type: 'text',
          fields: {
            english: {
              type: 'text',
              analyzer: 'english'
            }
          }
        }
      }
    }
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 1,
  body: {
    text: 'quick brown fox'
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 2,
  body: {
    text: 'quick brown foxes'
  }
)
puts response

response = client.search(
  index: 'my-index-000001',
  body: {
    query: {
      multi_match: {
        query: 'quick brown foxes',
        fields: [
          'text',
          'text.english'
        ],
        type: 'most_fields'
      }
    }
  }
)
puts response
{
	res, err := es.Indices.Create(
		"my-index-000001",
		es.Indices.Create.WithBody(strings.NewReader(`{
	  "mappings": {
	    "properties": {
	      "text": {
	        "type": "text",
	        "fields": {
	          "english": {
	            "type": "text",
	            "analyzer": "english"
	          }
	        }
	      }
	    }
	  }
	}`)),
	)
	fmt.Println(res, err)
}

{
	res, err := es.Index(
		"my-index-000001",
		strings.NewReader(`{
	  "text": "quick brown fox"
	} `),
		es.Index.WithDocumentID("1"),
		es.Index.WithPretty(),
	)
	fmt.Println(res, err)
}

{
	res, err := es.Index(
		"my-index-000001",
		strings.NewReader(`{
	  "text": "quick brown foxes"
	} `),
		es.Index.WithDocumentID("2"),
		es.Index.WithPretty(),
	)
	fmt.Println(res, err)
}

{
	res, err := es.Search(
		es.Search.WithIndex("my-index-000001"),
		es.Search.WithBody(strings.NewReader(`{
	  "query": {
	    "multi_match": {
	      "query": "quick brown foxes",
	      "fields": [
	        "text",
	        "text.english"
	      ],
	      "type": "most_fields"
	    }
	  }
	}`)),
		es.Search.WithPretty(),
	)
	fmt.Println(res, err)
}
PUT my-index-000001
{
  "mappings": {
    "properties": {
      "text": { 
        "type": "text",
        "fields": {
          "english": { 
            "type":     "text",
            "analyzer": "english"
          }
        }
      }
    }
  }
}

PUT my-index-000001/_doc/1
{ "text": "quick brown fox" } 

PUT my-index-000001/_doc/2
{ "text": "quick brown foxes" } 

GET my-index-000001/_search
{
  "query": {
    "multi_match": {
      "query": "quick brown foxes",
      "fields": [ 
        "text",
        "text.english"
      ],
      "type": "most_fields" 
    }
  }
}

text字段使用standard分析器。

text.english字段使用english分析器。

索引两个文档,一个包含fox,另一个包含foxes

查询texttext.english字段并组合分数。

text字段在第一个文档中包含术语fox,在第二个文档中包含foxestext.english字段在两个文档中都包含fox,因为foxes被词干还原为fox

查询字符串也由text字段的standard分析器和text.english字段的english分析器进行分析。词干还原后的字段允许对foxes的查询也匹配仅包含fox的文档。这使我们能够匹配尽可能多的文档。通过也查询未词干还原的text字段,我们提高了完全匹配foxes的文档的相关性分数。