Elasticsearch 5.4.3实战--Java API调用:索引mapping创建

因为项目开发使用的是Java语言, 项目的开发架构是Spring MVC+ maven的jar包管理,  所以今天重点说说ES 5.4.3 的Java API的源码实战

1. pom.xml文件增加依赖:

 1  <!-- elasticsearch -->
 2         <dependency>
 3           <groupId>org.elasticsearch</groupId>
 4           <artifactId>elasticsearch</artifactId>
 5           <version>5.4.3</version>
 6         </dependency>
 7         
 8         <dependency>
 9           <groupId>org.elasticsearch.client</groupId>
10           <artifactId>transport</artifactId>
11           <version>5.4.3</version>
12         </dependency>
13 
14         <dependency>
15             <groupId>org.apache.logging.log4j</groupId>
16             <artifactId>log4j-core</artifactId>
17             <version>2.6.2</version>
18         </dependency>
19         <dependency>
20             <groupId>org.apache.logging.log4j</groupId>
21             <artifactId>log4j-api</artifactId>
22             <version>2.6.2</version>
23         </dependency>
24         <dependency>
25             <groupId>org.apache.logging.log4j</groupId>
26             <artifactId>log4j-1.2-api</artifactId>
27             <version>2.6.2</version>
28         </dependency>

2. 首先我们创建一个获取Client 的Factory类,该类中的配置信息是配置在项目的.properties文件中

注意端口号通常为9300,这个是ES为java保留的默认端口号。

 1 package com.cs99lzzs.elasticsearch;
 2 
 3 import org.elasticsearch.client.Client;
 4 import org.elasticsearch.client.transport.TransportClient;
 5 import org.elasticsearch.common.network.InetAddresses;
 6 import org.elasticsearch.common.settings.Settings;
 7 import org.elasticsearch.common.transport.InetSocketTransportAddress;
 8 import org.elasticsearch.common.transport.TransportAddress;
 9 import org.elasticsearch.transport.client.PreBuiltTransportClient;
10 import org.springframework.beans.factory.annotation.Value;
11 import org.springframework.context.annotation.Bean;
12 import org.springframework.context.annotation.Configuration;
13 
14 @Configuration  
15 public class ElasticsearchFactory {  
16   
17     @Value("${elasticsearch.ips}")
18     private String ES_IPS;
19 
20     @Value("${elasticsearch.cluster.name}")
21     private String CLUSTER_NAME;
22 
23     @Value("${elasticsearch.port}")
24     private int ES_PORT;
25     
26     private static TransportClient transportClient = null;
27     
28     /** 
29      * 获取esClient实例
30      * @return
31      */
32     @Bean(name = "esClient")    
33     public Client getESClient(){  
34         
35         /**
36          * 1:通过 setting对象来指定集群配置信息
37          */
38         if (transportClient == null) {
39             Settings settings = Settings.builder()
40                     .put("cluster.name", CLUSTER_NAME)
41                     .put("client.transport.sniff", true)
42                     .build();
43             
44             transportClient = new  PreBuiltTransportClient(settings);
45             
46             String esIps[] = ES_IPS.split(",");
47             for (String esIp : esIps) {//添加集群IP列表
48                 TransportAddress transportAddress =  new InetSocketTransportAddress(InetAddresses.forString(esIp), ES_PORT);
49                 transportClient.addTransportAddresses(transportAddress);
50             }
51         }
52         return transportClient;  
53     }  
54 }  

3. 索引创建的Controller类, 主要是2个定时任务:全量更新和增量更新

另外一个重点就是:创建mapping。 该mapping包含了一个搜索提示的字段

  1 package com.cs99lzzs.elasticsearch;
  2 
  3 import java.net.InetAddress;
  4 import java.sql.Timestamp;
  5 
  6 import javax.annotation.Resource;
  7 import javax.servlet.http.HttpServletRequest;
  8 import javax.servlet.http.HttpServletResponse;
  9 
 10 import org.apache.commons.lang.StringUtils;
 11 import org.apache.log4j.Logger;
 12 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
 13 import org.elasticsearch.client.Client;
 14 import org.elasticsearch.client.Requests;
 15 import org.elasticsearch.client.transport.TransportClient;
 16 import org.elasticsearch.common.settings.Settings;
 17 import org.elasticsearch.common.transport.InetSocketTransportAddress;
 18 import org.elasticsearch.common.xcontent.XContentBuilder;
 19 import org.elasticsearch.common.xcontent.XContentFactory;
 20 import org.elasticsearch.transport.client.PreBuiltTransportClient;
 21 import org.springframework.beans.factory.annotation.Value;
 22 import org.springframework.scheduling.annotation.Scheduled;
 23 import org.springframework.stereotype.Controller;
 24 import org.springframework.web.bind.annotation.RequestMapping;
 25 import org.springframework.web.bind.annotation.RequestMethod;
 26 import org.springframework.web.bind.annotation.RequestParam;
 27 import org.springframework.web.bind.annotation.ResponseBody;
 28 
 29 import redis.clients.jedis.Jedis;
 30 
 31 import com.showjoy.data.page.JedisClient;
 32 import com.showjoy.elasticsearch.service.ProductIndexService;
 33 
 34 @Controller
 35 public class CreateIndexController {
 36     
 37     private static Logger logger = Logger.getLogger(CreateIndexController.class);
 38 
 39     private final static String   _REDIS_DB_STORE_TIME_KEY_NAME = "es.shop.index.update.time";
 40     private final static String   _PRODUCT_INDEX_TIME_KEY       = "es.shop.product.time";
 41     
 42     @Resource
 43     private ProductIndexService  productIndexService;
 44     
 45     @Resource(name="esClient")
 46     Client esClient;
 47 
 48     @Value("${elasticsearch.index}")
 49     private String CLUSTER_INDEX;
 50 
 51     @Value("${elasticsearch.type}")
 52     private String CLUSTER_TYPE;
 53     /**
 54      * 
 55      * @author chenxu
 56      * 2017年7月13日 下午6:25:54
 57      * @param request
 58      * @param response
 59      * @return
 60      */
 61     @ResponseBody
 62     @RequestMapping(value={"/", "/info"}, method = RequestMethod.GET)
 63     public String info(HttpServletRequest request, HttpServletResponse response) {
 64         return "success";
 65     }
 66     
 67     @ResponseBody
 68     @RequestMapping(value = "/es/index", method = RequestMethod.GET)
 69     public void productIndex(@RequestParam(required = false, defaultValue = "2016-01-05 00:00:00") String fromTime) {
 70         productIndexService.createIndex(Timestamp.valueOf(fromTime));
 71     }
 72     
 73 
 74     /**
 75      * 创建mapping
 76      * @author chenxu
 77      * 2017年7月10日 下午2:10:24
 78      * @param indices
 79      * @param mappingType
 80      * @throws Exception
 81      */
 82     public static void createMapping(String index, String type, Client client)
 83             throws Exception {
 84         XContentBuilder builder = XContentFactory.jsonBuilder()
 85                 .startObject()
 86                 .startObject(type)
 87                 .startObject("properties");
 88         //搜索字段: text类型, ik_max_word分词
 89         builder.startObject("brandZhName").field("type", "text").field("analyzer", "ik_max_word").field("store", "yes").endObject();
 90         builder.startObject("brandEnName").field("type", "text").field("analyzer", "ik_max_word").field("store", "yes").endObject();
 91         builder.startObject("brandAliases").field("type", "text").field("analyzer", "ik_max_word").field("store", "yes").endObject();
 92         builder.startObject("aliases").field("type", "text").field("analyzer", "ik_max_word").field("store", "yes").endObject();
 93         builder.startObject("zhName").field("type", "text").field("analyzer", "ik_max_word").field("store", "yes").endObject();
 94         builder.startObject("enName").field("type", "text").field("analyzer", "ik_max_word").field("store", "yes").endObject();
 95         //排序字段
 96         builder.startObject("price").field("type", "float").field("store", "yes").endObject();//现价
 97         builder.startObject("salesVolume").field("type", "integer").field("store", "yes").endObject();//销量
 98         builder.startObject("commission").field("type", "float").field("store", "yes").endObject();//收益
 99         //其他字段
100         /* integer */
101         builder.startObject("id").field("type", "integer").field("store", "yes").endObject();
102         builder.startObject("spuId").field("type", "integer").field("store", "yes").endObject();
103         builder.startObject("inventory").field("type", "integer").field("store", "yes").endObject();
104         builder.startObject("brandId").field("type", "integer").field("store", "yes").endObject();
105         builder.startObject("cateId").field("type", "integer").field("store", "yes").endObject();
106         builder.startObject("cateScope").field("type", "integer").field("store", "yes").endObject();
107         builder.startObject("vipShopId").field("type", "integer").field("store", "yes").endObject();
108         
109         /* boolean */
110         builder.startObject("isDelete").field("type", "boolean").field("store", "yes").endObject();
111         builder.startObject("triable").field("type", "boolean").field("store", "yes").endObject();
112         builder.startObject("isTrialPack").field("type", "boolean").field("store", "yes").endObject();
113         builder.startObject("searchable").field("type", "boolean").field("store", "yes").endObject();
114         builder.startObject("isHaitao").field("type", "boolean").field("store", "yes").endObject();
115         builder.startObject("isSupplier").field("type", "boolean").field("store", "yes").endObject();
116         
117         /* keyword */
118         builder.startObject("spuStatusId").field("type", "keyword").field("index", "no").field("store", "yes").endObject();
119         builder.startObject("image").field("type", "keyword").field("index", "no").field("store", "yes").endObject();
120         builder.startObject("isSuit").field("type", "keyword").field("index", "no").field("store", "yes").endObject();
121         builder.startObject("unit").field("type", "keyword").field("index", "no").field("store", "yes").endObject();
122         builder.startObject("sex").field("type", "keyword").field("index", "no").field("store", "yes").endObject();
123         builder.startObject("brandPathName").field("type", "keyword").field("index", "no").field("store", "yes").endObject();
124         builder.startObject("brandImage").field("type", "keyword").field("index", "no").field("store", "yes").endObject();
125         
126         builder.startObject("brandName").field("type", "keyword").field("store", "yes").endObject();
127         builder.startObject("cateName").field("type", "keyword").field("store", "yes").endObject();
128         builder.startObject("cateNameTree").field("type", "keyword").field("store", "yes").endObject();
129         builder.startObject("salesPromotionTag").field("type", "keyword").field("store", "yes").endObject(); //促销标签
130         
131         builder.startObject("perfumeType").field("type", "keyword").field("index", "no").field("store", "yes").endObject();
132         builder.startObject("brandScope").field("type", "keyword").field("index", "no").field("store", "yes").endObject();
133         
134         /* float */
135         builder.startObject("volume").field("type", "float").field("store", "yes").endObject();
136         builder.startObject("originalPrice").field("type", "float").field("store", "yes").endObject();
137         builder.startObject("discount").field("type", "float").field("store", "yes").endObject();
138         
139         /* date */
140         builder.startObject("gmtCreate").field("type", "date").field("store", "yes").endObject();
141         builder.startObject("gmtModified").field("type", "date").field("store", "yes").endObject();
142         
143         /* suggester */
144         builder.startObject("suggestName").field("type","completion").endObject();
145 //        builder.startObject("suggestBrandZhName").field("type","completion").field("analyzer","ik_max_word")
146 //                        .field("search_analyzer","ik_max_word").endObject();
147         
148         
149         //结束
150         builder.endObject().endObject().endObject();
151         
152         PutMappingRequest mapping = Requests.putMappingRequest(index)
153                 .type(type).source(builder);
154         client.admin().indices().putMapping(mapping).actionGet();
155         
156     }
157     
158     /**
159      * 全量更新商品索引任务,凌晨4点执行
160      * @author chenxu
161      * 
162      **/
163     @Scheduled(cron = "0 0 4 * * ?")
164     @ResponseBody
165     @RequestMapping(value = "/search/index/allproduct", method = RequestMethod.GET)
166     public void indexProducts(){
167         Timestamp updateTime = new Timestamp(0);
168         saveTimestamp(_PRODUCT_INDEX_TIME_KEY, new Timestamp(System.currentTimeMillis()));
169         productIndexService.createIndex(updateTime);
170     }
171 
172     /**
173      * 增量更新商品索引 ,每隔5分钟执行
174      * @author chenxu
175      * 
176      **/
177     @Scheduled(cron = "0 */5 * * * ?")
178     @ResponseBody
179     @RequestMapping(value = "/search/index/product", method = RequestMethod.GET)
180     public void indexProduct() {
181         Timestamp updateTime = getTimestamp(_PRODUCT_INDEX_TIME_KEY);
182         long currentTimeMillis = System.currentTimeMillis();
183         productIndexService.createIndex(updateTime);
184         saveTimestamp(_PRODUCT_INDEX_TIME_KEY, new Timestamp(currentTimeMillis));
185     }
186     
187     private static Timestamp getTimestamp(String name) {
188         Timestamp timestamp = null;
189         try {
190             Jedis jedis = JedisClient.getJedis();
191             jedis.select(1);
192             String timestr = jedis.hget(_REDIS_DB_STORE_TIME_KEY_NAME, name);
193             JedisClient.returnResource(jedis);
194             if (StringUtils.isNotBlank(timestr)) {
195                 timestamp = Timestamp.valueOf(timestr);
196             } else {
197                 timestamp = new Timestamp(0);
198             }
199         } catch (Exception e) {
200             logger.error("elasticsearch获取索引最新更新时间失败,检查存储redis是否出现问题", e);
201             timestamp = new Timestamp(System.currentTimeMillis());
202         }
203         return timestamp;
204     }
205     
206     private void saveTimestamp(String name, Timestamp timestamp) {
207         try {
208             Jedis jedis = JedisClient.getJedis();
209             jedis.select(1);
210             jedis.hset(_REDIS_DB_STORE_TIME_KEY_NAME, name, timestamp.toString());
211             JedisClient.returnResource(jedis);
212         } catch (Exception e) {
213             logger.error("存储索引最新更新时间失败,检查存储redis是否出现问题", e);
214         }
215     }
216     
217     
218     public static void main(String[] args) {
219         Settings settings = Settings.builder()
220                 .put("cluster.name", "showjoy-shop-search")
221                 .put("client.transport.sniff", true)
222                 .build();
223 
224         TransportClient tc = new PreBuiltTransportClient(settings);
225         try {
226             
227             tc.addTransportAddress(
228                     new InetSocketTransportAddress(InetAddress.getByName("192.168.0.124"), 9300));
229             
230             createMapping("item_index", "shop_item", tc);
231             // 去数据库中扫描达人店商品的待搜索字段
232 //            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss");
233 //            Map<String, Object> source = new HashMap<String, Object>();
234 //            source.put("name", "酒");
235 //            source.put("cateId", 5);
236 //            source.put("brandId", 15);
237 //            source.put("salesVolume", 250);
238 //            source.put("price", 55.00d);
239 //            source.put("income", 5.5d);
240 //            source.put("createDate", sdf.format(new Date()));
241 //
242 //            // 增加
243 //            IndexResponse addResponse = tc
244 //                    .prepareIndex("item_index", "shop_item", "1")
245 //                    .setSource(source).get();
246 //
247 //            if (addResponse != null
248 //                    && addResponse.getShardInfo().getSuccessful() == 1) {
249 //                if (Result.CREATED.equals(addResponse.getResult())) {
250 //                    System.err.println("create success");
251 //                } else {
252 //                    System.err.println("update success");
253 //                }
254 //            } else {
255 //                System.err.println(JSON.toJSONString(addResponse));
256 //            }
257             
258         } catch (Exception e) {
259             e.printStackTrace();
260         }
261         if (tc != null) {
262             tc.close();
263         }
264         
265         System.err.println("finished");
266     }
267 }

4.  先在head插件中创建你自己的index名字,执行main函数, 就能在它下面创建相应的mapping。

批量写入数据,请看下篇: http://www.cnblogs.com/cs99lzzs/p/7212474.html

原文地址:https://www.cnblogs.com/cs99lzzs/p/7212428.html