2020年7月31日更,以下方法太麻烦,请移步,我经过测试,发现该博主的方法在我这边需要先createIndex后putMapping,否则会报错。此外,定义的实体类中必须含有@Id定义的id属性,否则也会报错。

但是以上方法仍然是有短板的,因为根据@Field来定义数据类型时,是只有String, Integer, Long, Date, Float, Double, Boolean, Object, Auto, Nested, Ip, Attachment这几个类型可以定义,无法定义byte和short(代码里FieldType枚举类中就没定义这俩),所以即使是一个很小的数字也必须使用Integer来装(而使用@Mapping标签时用的配置文件可以定义byte)。网上很多都有说在满足需求的情况下,尽可能选择范围小的数据类型。我经过测试,发现同样的数据,使用byte所占存储空间明显比Integer或Long要小,至于查询效率会不会被影响,我没测过。所以使用@Field还是@Mapping这就要看自己的具体需要了。

-------------------------------------------------

elasticsearch2.4版本,使用spring-data-elasticsearch-2.1.23.RELEASE.jar来操作,发现实体类的Field标签定义的内容无效。查阅多方资料说是spring-data-elasticsearch根本没有使用该标签。按网上的解决方法是使用mappingPath标签,如下:

@Document(indexName = "#{index.indexName}", type = "txt", replicas = 0, shards = 1)
@Mapping(mappingPath = "es-logXXXXXX.json")
public class LogEntity {
	private String name;
	private int day;
	private int num;
	private String text;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getDay() {
		return day;
	}

	public void setDay(int day) {
		this.day = day;
	}

	public int getNum() {
		return num;
	}

	public void setNum(int num) {
		this.num = num;
	}

	public String getText() {
		return text;
	}

	public void setText(String text) {
		this.text = text;
	}
}

Document里indexName的写法是我动态设置bean来实现动态index名称,与本问题无关。在项目src路径下建立一个文件es-logXXXXXX.json,如下:

{
	"properties": {
		"num": {
			"type": "long"
		},
		"name": {
			"type": "string",
			"index": "not_analyzed"
		},
		"text": {
			"type": "string",
			"analyzer": "whitespace"
		},
		"day": {
			"type": "long"
		}
	}
}

这样设置后新创建的index还是无效,与网上教程没有区别啊,是否与我使用的是ElasticsearchTemplate有关呢?

总之就是,在我的代码中还缺少了一步,就是要加上elasticsearchTemplate.putMapping(LogEntity.class);这句代码。

第一步,以上俩文件齐全后,调用

elasticsearchTemplate.createIndex(LogEntity.class);

创建index后,索引信息如下,可以看到mappings属性是空的,没有任何我在es-logXXXXXX.json里定义的内容。

{
	"state": "open",
	"settings": {
		"index": {
			"refresh_interval": "1s",
			"number_of_shards": "1",
			"creation_date": "1587014790803",
			"store": {
				"type": "fs"
			},
			"number_of_replicas": "0",
			"uuid": "FKHOqrlySGS6o4609ot6DA",
			"version": {
				"created": "2040699"
			}
		}
	},
	"mappings": {
		
	},
	"aliases": []
}

第二步,在插入数据之前,调用(也是我上边说的少的那步)

elasticsearchTemplate.putMapping(LogEntity.class);

最后插入数据,索引信息会变为如下这样

{
	"state": "open",
	"settings": {
		"index": {
			"refresh_interval": "1s",
			"number_of_shards": "1",
			"creation_date": "1587535172761",
			"store": {
				"type": "fs"
			},
			"number_of_replicas": "0",
			"uuid": "HMA_0C_YTuiYrA0fKf42vQ",
			"version": {
				"created": "2040699"
			}
		}
	},
	"mappings": {
		"txt": {
			"properties": {
				"num": {
					"type": "long"
				},
				"name": {
					"index": "not_analyzed",
					"type": "string"
				},
				"text": {
					"analyzer": "whitespace",
					"type": "string"
				},
				"day": {
					"type": "long"
				}
			}
		}
	},
	"aliases": []
}

可以看到,mappings里有了属性值,用查询数据来验证分词器和是否分词都已生效。

如果在插入数据之前没有使用elasticsearchTemplate.putMapping(LogEntity.class);,那么mappings里会生成默认的值,而不会使用我的配置。