elasticsearch 字段别名(创建索引并指定索引类型的mapping)

本文介绍如何在Elasticsearch中通过自定义Mapping来解决字段被误分词的问题,并演示如何使用term aggregation统计特定字段的频次。

ES默认是动态创建索引和索引类型的mapping的。这就相当于无需定义Solr中的Schema,无需指定各个字段的索引规则就可以索引文件,很方便。但有时方便就代表着不灵活。比如,ES默认一个字段是要做分词的,但我们有时要搜索匹配整个字段却不行。如有统计工作要记录每个城市出现的次数。对于NAME字段,若记录“new york”文本,ES可能会把它拆分成“new”和“york”这两个词,分别计算这个两个单词的次数,而不是我们期望的“new york”。

这时,就需要我们在创建索引时定义mapping。假设索引叫index_name,索引类型的名字叫index_type,编写mapping文件如下(注意:mapping文件中,index_type必须与实际索引当中的索引类型完全一致。):

{	
	   "index_type":{  
		  "properties":{  
			 "ID":{  
				"type":"string",  
				"index":"not_analyzed"   
			 },  			 
			 "NAME":{
				"type":"string",
				"fields":{
					"NAME":{
						"type":"string"
					},
					"raw":{
						"type":"string",
						"index":"not_analyzed"	
					}
				}					
			 } 		 	 		
		  }  
	   }   
}

以上文件是说我们对于index_type这个索引类型,定义了它的mapping。重点是将NAME这个字段映射为两个,一个是需要做索引分析的NAME,另一个是不分析的raw,即不会拆分new york这种词组。这样我们在做搜索的时候,就可以对NAME.raw这个字段做term aggregation,获得所有城市出现的次数了。term aggregation的REST方式的请求编写如下:

{
  "query": {
    "match_all": {}
  },
  "aggregations": {
    "cityAggs": {
      "terms": {
        "field""NAME.raw"
      }
    }
  }
}
<think>我们正在讨论的是Elasticsearch中删除索引指定字段的方法。注意:在Elasticsearch中,一旦字段创建,就不能直接删除。这是因为映射(mapping)是不可变的(除了某些特定情况,如添加新字段)。因此,我们需要采用其他策略来达到“删除字段”的效果。 常见方法: 1. 重建索引创建一个新索引,将旧索引的数据复制到新索引,但在复制过程中排除不需要的字段。然后删除旧索引将新索引重命名为旧索引的名称(或者使用别名切换)。 2. 使用脚本更新现有文档:通过_update_by_query操作,使用painless脚本将指定字段从文档中移除。但请注意,这不会从映射中删除字段,只是从文档的_source中删除该字段的值。而且,映射中仍然会保留该字段的定义。 3. 如果只是不想在查询结果中看到该字段,可以使用_source过滤,在查询时排除该字段。但这没有真正删除数据,只是返回结果中不显示。 根据需求,如果我们想要彻底删除字段(包括数据和映射定义),重建索引是推荐的方法。 步骤: 1. 创建一个新的索引,新索引的映射中不包含要删除的字段。 2. 使用reindex API将旧索引的数据复制到新索引在reindex过程中使用_source过滤,排除不需要的字段。 3. 删除旧索引。 4. 将新索引重命名为旧索引的名称,或者使用别名指向新索引。 示例: 假设我们有一个索引名为`my_index`,其中包含一个字段`unwanted_field`,我们想要删除这个字段。 步骤1:创建索引(可以手动定义映射,也可以从旧索引复制映射删除不需要的字段定义,但通常我们选择重新定义映射) 我们使用PUT请求创建索引`my_index_new`,定义我们想要的映射(不包含`unwanted_field`)。如果其他字段保持不变,我们可以从旧索引获取映射,然后删除不需要的字段定义,再用于新索引。 步骤2:使用reindex API,在_source中排除`unwanted_field` ```json POST _reindex { "source": { "index": "my_index", "_source": ["field1", "field2", ...] // 只列出你需要的字段,或者使用exclude排除 }, "dest": { "index": "my_index_new" } } ``` 或者使用exclude: ```json POST _reindex { "source": { "index": "my_index", "_source": { "exclude": ["unwanted_field"] } }, "dest": { "index": "my_index_new" } } ``` 步骤3:删除旧索引 ```json DELETE my_index ``` 步骤4:将新索引重命名为旧索引名称 ```json POST /_aliases { "actions": [ { "add": { "index": "my_index_new", "alias": "my_index" } } ] } ``` 然后删除原来的索引(如果已经删除了旧索引,那么这里可以直接将新索引重命名为旧索引的名称,但Elasticsearch不支持直接重命名索引,所以通常使用别名或者先删除旧索引创建别名。另一种方法是使用索引别名,将原来的别名指向新索引,然后删除旧索引)。 更常见的做法是:在删除旧索引后,将新索引重命名为旧索引的名字(通过别名切换,或者使用_reindex后直接切换别名)。 注意:如果应用中使用的是索引别名,那么可以在reindex完成后,将别名从旧索引切换到新索引,这样对应用透明。 具体操作: 1. 假设`my_index`有一个别名`my_index_alias`,那么我们在reindex完成后,执行以下操作: ```json POST /_aliases { "actions": [ { "remove": { "index": "my_index", "alias": "my_index_alias" }}, { "add": { "index": "my_index_new", "alias": "my_index_alias" }} ] } ``` 2. 然后删除旧索引`my_index`。 如果没有别名,那么你可能需要修改应用程序中的索引名称,或者将新索引重命名为旧索引的名称(但Elasticsearch不支持直接重命名,所以需要先创建别名,或者使用其他方法)。 另一种重命名索引的方法:使用reindex后,将旧索引删除,然后创建一个新索引别名别名为旧索引名(如果应用允许使用别名,那么这是最好的方式)。 但是,如果应用就是使用索引名(而不是别名)访问,那么你可能需要将新索引的名字改为旧索引的名字。由于Elasticsearch不支持直接重命名,所以只能: 1. 删除旧索引(`my_index`) 2. 然后创建索引(`my_index_new`)的别名为`my_index`(前提是应用允许通过别名访问,但注意别名索引名在使用上大部分情况是兼容的,但有些操作如创建索引不能用别名,所以如果应用是直接使用索引名,那么创建别名`my_index`后,应用可以像使用索引一样使用这个别名,但注意:有些操作比如创建索引的映射设置等不能通过别名操作,需要直接操作索引。所以如果应用有创建索引的需求,那么这种方法就不行,需要重建索引为原名称)。 实际上,我们无法将新索引直接重命名为旧索引的名称(因为ES不允许直接重命名索引),所以只能通过以下步骤: 1. 删除旧索引(`my_index`) 2. 创建索引(`my_index_new`)的别名(`my_index`) 但是,如果应用中有创建索引的操作(比如初始化时创建索引),那么使用别名可能会遇到问题。因此,在删除旧索引后,我们可以创建一个新索引,名字为`my_index`(此时旧索引已经被删除,所以名字可用),然后再次将数据从`my_index_new` reindex到`my_index`,最后删除`my_index_new`。这样操作会有两次reindex,数据量大时可能比较耗时。 因此,最佳实践是使用别名,避免在应用中使用硬编码的索引名。 总结:删除索引指定字段的步骤是重建索引排除该字段。 另外,如果只是想在查询结果中不返回该字段,可以使用_source过滤,例如: ```json GET my_index/_search { "_source": { "excludes": ["unwanted_field"] }, "query": {...} } ``` 但是,如果我们的目标是减少存储空间,那么必须重建索引,因为_source过滤只是在返回结果时去掉字段,而数据本身仍然存储在_source中。 因此,根据你的需求选择合适的方法。 注意:以上操作需要谨慎,建议在生产环境中操作前先备份数据。 现在,我们来回答用户的问题:Elasticsearch删除索引指定field的方法。 结论:由于Elasticsearch的映射一旦创建就不能直接修改(删除字段),因此要删除字段,需要重建索引排除该字段,然后替换旧索引。 步骤总结: 1. 创建一个新索引,新索引的映射中不包含要删除的字段。 2. 使用Reindex API将旧索引的数据复制到新索引在_source中排除要删除的字段(或者只包含需要的字段)。 3. 删除旧索引。 4. 将新索引重命名为旧索引的名称(通过别名或重新创建索引的方式)。 注意:如果索引很大,reindex可能会花费较长时间,且需要足够的磁盘空间。 相关问题: 1. 在Elasticsearch中,如何安全地重建索引? 2. 使用Reindex API时有哪些注意事项? 3. 如何为Elasticsearch索引设置别名? 4. 除了重建索引,还有其他方法可以删除字段吗? 5. 在重建索引过程中,如何保证数据的一致性?</think>在 Elasticsearch 中,**无法直接删除已存在索引中的字段**(field),因为映射(mapping)一旦创建就不可修改(除少数例外,如添加新字段)。以下是可行的解决方案: --- ### 方法 1:重建索引(推荐) 通过创建索引排除目标字段,再迁移数据: 1. **创建索引**(排除目标字段): ```json PUT /new_index { "mappings": { "properties": { "keep_field1": { "type": "text" }, // 保留的字段 "keep_field2": { "type": "keyword" } // 不包含需删除的字段(如 unwanted_field) } } } ``` 2. **迁移数据**(使用 `_reindex` 过滤字段): ```json POST _reindex { "source": { "index": "old_index", "_source": ["keep_field1", "keep_field2"] // 仅包含需保留的字段 }, "dest": { "index": "new_index" } } ``` 3. **切换别名或删除旧索引**: ```json POST /_aliases { "actions": [ { "remove": { "index": "old_index", "alias": "my_alias" }}, { "add": { "index": "new_index", "alias": "my_alias" }} ] } ``` 完成后删除旧索引:`DELETE /old_index` --- ### 方法 2:从文档中隐藏字段(不删除数据) 若仅需在查询结果中隐藏字段(不减少存储空间): ```json GET /my_index/_search { "_source": { "excludes": ["unwanted_field"] // 排除目标字段 }, "query": { ... } } ``` --- ### 方法 3:使用脚本移除字段值(慎用) 通过 `_update_by_query` 从文档的 `_source` 中删除字段值(但**映射仍保留该字段**): ```json POST /my_index/_update_by_query { "script": { "source": "ctx._source.remove('unwanted_field')", "lang": "painless" } } ``` > **注意**:此操作不删除映射中的字段定义,且可能影响性能。 --- ### 关键说明 1. **映射不可变性**:Elasticsearch 不允许直接删除已存在的映射字段[^1]。 2. **存储影响**:方法 1 是唯一能减少存储空间的方案。 3. **别名的重要性**:使用别名(alias)可避免应用中断。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值