• 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

  • 相关阅读:
    存储过程分页,前台应用范例repeater分页
    引用真正分页控件(与存储过程联合使用)页面
    分页存储过程repeater分页
    查找DetailsView1数据控件中的数据
    c#读取文件
    SQL触发器实例讲解
    TreeView节点选中问题
    C# 实现版本自动更新
    .Net那点事儿系列:C#操作Xml:通过XmlDocument读写Xml文档
    Linq学习笔记
  • 原文地址:https://www.cnblogs.com/cs99lzzs/p/7212428.html
Copyright © 2020-2023  润新知