基于 Elasticsearch 8.12.0 集群创建索引
索引创建
创建一个产品的索引
解释:
productId: 产品的唯一标识符,使用 keyword 类型,适合精确匹配和聚合操作。name: 产品名称,使用 text 类型进行全文搜索,同时包含一个 keyword 子字段用于精确匹配。description: 产品描述,使用 text 类型进行全文搜索。price: 产品价格,使用 float 类型。category: 产品类别,使用 keyword 类型,适合精确匹配和聚合操作。brand: 产品品牌,使用 keyword 类型。inStock: 产品库存状态,使用 boolean 类型。tags: 产品标签,使用 keyword 类型,适合精确匹配和聚合操作。createdAt 和 updated_at: 产品的创建和更新时间,使用 date 类型,支持多种日期格式。attributes: 产品的属性,使用 nested 类型,允许存储键值对形式的属性。curl --location --request PUT 'http://127.0.0.1:9200/product_data_index' \
--data '{"settings": {"number_of_shards": 5,"number_of_replicas": 1},"mappings": {"properties": {"productId": {"type": "keyword"},"name": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}},"description": {"type": "text"},"price": {"type": "float"},"category": {"type": "keyword"},"brand": {"type": "keyword"},"inStock": {"type": "boolean"},"tags": {"type": "keyword"},"createdAt": {"type": "date","format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"},"updatedAt": {"type": "date","format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"},"attributes": {"type": "nested","properties": {"key": {"type": "keyword"},"value": {"type": "text"}}}}}
}'
KIbana新增测试数据
POST /product_data_index/_bulk
{"index": {"_index": "product_data_index"}}
{"productId": "P001", "name": "华为手机", "description": "高性能5G手机,搭载麒麟芯片,支持超快充电。", "price": 3999.0, "category": "电子产品", "brand": "华为", "inStock": true, "tags": ["手机", "5G", "华为"], "createdAt": "2025-03-18 10:00:00", "updatedAt": "2025-03-18 10:00:00", "attributes": [{"key": "颜色", "value": "黑色"}, {"key": "内存", "value": "8GB"}]}
{"index": {"_index": "product_data_index"}}
{"productId": "P002", "name": "小米电视", "description": "4K高清智能电视,支持多种流媒体应用。", "price": 2999.0, "category": "家电", "brand": "小米", "inStock": true, "tags": ["电视", "4K", "小米"], "createdAt": "2025-03-18 11:00:00", "updatedAt": "2025-03-18 11:00:00", "attributes": [{"key": "尺寸", "value": "55英寸"}, {"key": "分辨率", "value": "4K"}]}
{"index": {"_index": "product_data_index"}}
{"productId": "P003", "name": "苹果笔记本电脑", "description": "轻薄便携,搭载苹果M1芯片,性能强劲。", "price": 9999.0, "category": "电子产品", "brand": "苹果", "inStock": false, "tags": ["笔记本电脑", "苹果", "M1芯片"], "createdAt": "2025-03-18 12:00:00", "updatedAt": "2025-03-18 12:00:00", "attributes": [{"key": "内存", "value": "16GB"}, {"key": "存储", "value": "512GB SSD"}]}
{"index": {"_index": "product_data_index"}}
{"productId": "P004", "name": "联想台式电脑", "description": "高性能办公电脑,适合多任务处理。", "price": 5999.0, "category": "电子产品", "brand": "联想", "inStock": true, "tags": ["台式电脑", "联想", "办公"], "createdAt": "2025-03-18 13:00:00", "updatedAt": "2025-03-18 13:00:00", "attributes": [{"key": "处理器", "value": "Intel Core i7"}, {"key": "显卡", "value": "NVIDIA GeForce"}]}
{"index": {"_index": "product_data_index"}}
{"productId": "P005", "name": "美的空调", "description": "智能变频空调,节能高效,适合家庭使用。", "price": 3499.0, "category": "家电", "brand": "美的", "inStock": true, "tags": ["空调", "美的", "变频"], "createdAt": "2025-03-18 14:00:00", "updatedAt": "2025-03-18 14:00:00", "attributes": [{"key": "制冷量", "value": "1.5匹"}, {"key": "功能", "value": "冷暖两用"}]}
对应实体
import lombok.Data;import java.util.List;
import java.util.Map;/*** 功能描述** @author jason*/
@Data
public class EsProduct {/*** 商品唯一ID(如:P001)*/private String productId;/*** 商品名称(如:华为手机)*/private String name;/*** 商品详细描述* 示例:高性能5G手机,搭载麒麟芯片,支持超快充电。*/private String description;/*** 商品价格(单位:元)* 示例:3999.00*/private double price;/*** 商品分类* 示例:电子产品*/private String category;/*** 品牌名称* 示例:华为*/private String brand;/*** 库存状态* true-有货,false-无货*/private boolean inStock;/*** 商品标签列表* 示例:["手机", "5G", "华为"]*/private List<String> tags;/*** 创建时间(格式:yyyy-MM-dd HH:mm:ss)* 示例:2025-03-18 10:00:00*/private String createdAt;/*** 最后更新时间(格式:yyyy-MM-dd HH:mm:ss)* 示例:2025-03-18 10:00:00*/private String updatedAt;/*** 商品属性(JSON字符串格式)* 示例:[{"key":"颜色","value":"黑色"},{"key":"内存","value":"8GB"}]*/private List<Map<String, String>> attributes;}
脚本批量创建测试数据
package org.example.es;import org.example.es.entity.EsProduct;import java.text.SimpleDateFormat;
import java.util.*;/*** 测试数据生产类*/
public class TestDataGenerator {private static final Random random = new Random();private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 预定义的品牌和分类private static final String[] BRANDS = {"华为", "小米", "苹果", "三星", "OPPO", "vivo", "荣耀", "一加", "realme", "iQOO"};private static final String[] CATEGORIES = {"智能手机", "笔记本电脑", "平板电脑", "智能手表", "耳机", "智能家居", "数码配件"};// 手机型号后缀private static final String[] PHONE_MODELS = {"Pro", "Plus", "Max", "Lite", "SE", "Ultra", "X", "Z"};// 颜色选项private static final String[] COLORS = {"黑色", "白色", "蓝色", "红色", "绿色", "紫色", "银色", "金色"};// 内存选项private static final String[] MEMORIES = {"4GB", "6GB", "8GB", "12GB", "16GB"};// 存储选项private static final String[] STORAGES = {"64GB", "128GB", "256GB", "512GB", "1TB"};/*** 获取产品测试数据* <p>* size 条数*/public static List<EsProduct> getTestEsProductList(int size) {List<EsProduct> esProductList = new ArrayList<>();for (int i = 0; i < size; i++) {EsProduct product = new EsProduct();// 生成产品IDproduct.setProductId("P" + String.format("%05d", i + 1));// 生成产品名称String brand = BRANDS[random.nextInt(BRANDS.length)];String model = random.nextInt(20) + "";String modelSuffix = PHONE_MODELS[random.nextInt(PHONE_MODELS.length)];product.setName(brand + " " + model + modelSuffix);// 生成描述product.setDescription(generateDescription(brand, product.getName()));// 生成价格 (500-15000之间的随机值,以99或00结尾)int basePrice = 500 + random.nextInt(14500);int priceEnding = random.nextBoolean() ? 99 : 00;product.setPrice(basePrice - (basePrice % 100) + priceEnding);// 设置分类product.setCategory(CATEGORIES[random.nextInt(CATEGORIES.length)]);// 设置品牌product.setBrand(brand);// 库存状态 (80%概率有货)product.setInStock(random.nextDouble() < 0.8);// 生成标签product.setTags(generateTags(brand, product.getCategory()));// 生成创建和更新时间 (过去365天内随机时间)Date now = new Date();Date randomDate = new Date(now.getTime() - (long) (random.nextDouble() * 365 * 24 * 60 * 60 * 1000));product.setCreatedAt(dateFormat.format(randomDate));// 更新时间比创建时间晚1-30天Date updateDate = new Date(randomDate.getTime() + (long) (1 + random.nextInt(30)) * 24 * 60 * 60 * 1000);product.setUpdatedAt(dateFormat.format(updateDate));// 生成属性product.setAttributes(generateAttributes());esProductList.add(product);}return esProductList;}private static String generateDescription(String brand, String name) {String[] features = {"高性能处理器", "超长续航", "高清显示屏", "快速充电", "多摄像头系统","5G网络支持", "大容量电池", "轻薄设计", "防水防尘", "高刷新率屏幕"};// 随机选择3-5个特性Collections.shuffle(Arrays.asList(features));int featureCount = 3 + random.nextInt(3);StringBuilder desc = new StringBuilder(brand + " " + name + ",");for (int i = 0; i < featureCount; i++) {desc.append(features[i]);if (i < featureCount - 1) {desc.append(",");}}desc.append("。");return desc.toString();}private static List<String> generateTags(String brand, String category) {List<String> tags = new ArrayList<>();tags.add(brand);tags.add(category);// 添加一些通用标签String[] commonTags = {"新品", "热销", "旗舰", "性价比", "2025新款"};if (random.nextBoolean()) {tags.add(commonTags[random.nextInt(commonTags.length)]);}// 如果是手机,添加5G标签if (category.contains("手机") && random.nextDouble() > 0.3) {tags.add("5G");}return tags;}private static List<Map<String, String>> generateAttributes() {List<Map<String, String>> attributes = new ArrayList<>();// 颜色属性Map<String, String> colorAttr = new HashMap<>();colorAttr.put("key", "颜色");colorAttr.put("value", COLORS[random.nextInt(COLORS.length)]);attributes.add(colorAttr);// 内存属性if (random.nextDouble() > 0.2) { // 80%概率有内存属性Map<String, String> memoryAttr = new HashMap<>();memoryAttr.put("key", "内存");memoryAttr.put("value", MEMORIES[random.nextInt(MEMORIES.length)]);attributes.add(memoryAttr);}// 存储属性if (random.nextDouble() > 0.2) { // 80%概率有存储属性Map<String, String> storageAttr = new HashMap<>();storageAttr.put("key", "存储");storageAttr.put("value", STORAGES[random.nextInt(STORAGES.length)]);attributes.add(storageAttr);}return attributes;}}
批量创建文档 2w 笔
@Testvoid bulkCreateDocument() {List<EsProduct> esProductList = TestDataGenerator.getTestEsProductList(20000);BulkResponse result = esClient.bulkCreateDocument("product_data_index", esProductList);if (result.errors()) {// 至少有一个操作失败for (BulkResponseItem item : result.items()) {if (item.error() != null) {log.info("批量插入数据,部分失败:{}", item.error().reason());}}} else {// 所有操作成功log.info("批量插入数据成功");}}