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

时间:2023-03-09 06:54:01
Elasticsearch 5.4.3实战--Java API调用:索引mapping创建

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

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

  <!-- elasticsearch -->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>5.4.3</version>
</dependency> <dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>5.4.3</version>
</dependency> <dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-1.2-api</artifactId>
<version>2.6.2</version>
</dependency>

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

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

 package com.cs99lzzs.elasticsearch;

 import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.network.InetAddresses;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; @Configuration
public class ElasticsearchFactory { @Value("${elasticsearch.ips}")
private String ES_IPS; @Value("${elasticsearch.cluster.name}")
private String CLUSTER_NAME; @Value("${elasticsearch.port}")
private int ES_PORT; private static TransportClient transportClient = null; /**
* 获取esClient实例
* @return
*/
@Bean(name = "esClient")
public Client getESClient(){ /**
* 1:通过 setting对象来指定集群配置信息
*/
if (transportClient == null) {
Settings settings = Settings.builder()
.put("cluster.name", CLUSTER_NAME)
.put("client.transport.sniff", true)
.build(); transportClient = new PreBuiltTransportClient(settings); String esIps[] = ES_IPS.split(",");
for (String esIp : esIps) {//添加集群IP列表
TransportAddress transportAddress = new InetSocketTransportAddress(InetAddresses.forString(esIp), ES_PORT);
transportClient.addTransportAddresses(transportAddress);
}
}
return transportClient;
}
}

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

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

 package com.cs99lzzs.elasticsearch;

 import java.net.InetAddress;
import java.sql.Timestamp; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.Requests;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import redis.clients.jedis.Jedis; import com.showjoy.data.page.JedisClient;
import com.showjoy.elasticsearch.service.ProductIndexService; @Controller
public class CreateIndexController { private static Logger logger = Logger.getLogger(CreateIndexController.class); private final static String _REDIS_DB_STORE_TIME_KEY_NAME = "es.shop.index.update.time";
private final static String _PRODUCT_INDEX_TIME_KEY = "es.shop.product.time"; @Resource
private ProductIndexService productIndexService; @Resource(name="esClient")
Client esClient; @Value("${elasticsearch.index}")
private String CLUSTER_INDEX; @Value("${elasticsearch.type}")
private String CLUSTER_TYPE;
/**
*
* @author chenxu
* 2017年7月13日 下午6:25:54
* @param request
* @param response
* @return
*/
@ResponseBody
@RequestMapping(value={"/", "/info"}, method = RequestMethod.GET)
public String info(HttpServletRequest request, HttpServletResponse response) {
return "success";
} @ResponseBody
@RequestMapping(value = "/es/index", method = RequestMethod.GET)
public void productIndex(@RequestParam(required = false, defaultValue = "2016-01-05 00:00:00") String fromTime) {
productIndexService.createIndex(Timestamp.valueOf(fromTime));
} /**
* 创建mapping
* @author chenxu
* 2017年7月10日 下午2:10:24
* @param indices
* @param mappingType
* @throws Exception
*/
public static void createMapping(String index, String type, Client client)
throws Exception {
XContentBuilder builder = XContentFactory.jsonBuilder()
.startObject()
.startObject(type)
.startObject("properties");
//搜索字段: text类型, ik_max_word分词
builder.startObject("brandZhName").field("type", "text").field("analyzer", "ik_max_word").field("store", "yes").endObject();
builder.startObject("brandEnName").field("type", "text").field("analyzer", "ik_max_word").field("store", "yes").endObject();
builder.startObject("brandAliases").field("type", "text").field("analyzer", "ik_max_word").field("store", "yes").endObject();
builder.startObject("aliases").field("type", "text").field("analyzer", "ik_max_word").field("store", "yes").endObject();
builder.startObject("zhName").field("type", "text").field("analyzer", "ik_max_word").field("store", "yes").endObject();
builder.startObject("enName").field("type", "text").field("analyzer", "ik_max_word").field("store", "yes").endObject();
//排序字段
builder.startObject("price").field("type", "float").field("store", "yes").endObject();//现价
builder.startObject("salesVolume").field("type", "integer").field("store", "yes").endObject();//销量
builder.startObject("commission").field("type", "float").field("store", "yes").endObject();//收益
//其他字段
/* integer */
builder.startObject("id").field("type", "integer").field("store", "yes").endObject();
builder.startObject("spuId").field("type", "integer").field("store", "yes").endObject();
builder.startObject("inventory").field("type", "integer").field("store", "yes").endObject();
builder.startObject("brandId").field("type", "integer").field("store", "yes").endObject();
builder.startObject("cateId").field("type", "integer").field("store", "yes").endObject();
builder.startObject("cateScope").field("type", "integer").field("store", "yes").endObject();
builder.startObject("vipShopId").field("type", "integer").field("store", "yes").endObject(); /* boolean */
builder.startObject("isDelete").field("type", "boolean").field("store", "yes").endObject();
builder.startObject("triable").field("type", "boolean").field("store", "yes").endObject();
builder.startObject("isTrialPack").field("type", "boolean").field("store", "yes").endObject();
builder.startObject("searchable").field("type", "boolean").field("store", "yes").endObject();
builder.startObject("isHaitao").field("type", "boolean").field("store", "yes").endObject();
builder.startObject("isSupplier").field("type", "boolean").field("store", "yes").endObject(); /* keyword */
builder.startObject("spuStatusId").field("type", "keyword").field("index", "no").field("store", "yes").endObject();
builder.startObject("image").field("type", "keyword").field("index", "no").field("store", "yes").endObject();
builder.startObject("isSuit").field("type", "keyword").field("index", "no").field("store", "yes").endObject();
builder.startObject("unit").field("type", "keyword").field("index", "no").field("store", "yes").endObject();
builder.startObject("sex").field("type", "keyword").field("index", "no").field("store", "yes").endObject();
builder.startObject("brandPathName").field("type", "keyword").field("index", "no").field("store", "yes").endObject();
builder.startObject("brandImage").field("type", "keyword").field("index", "no").field("store", "yes").endObject(); builder.startObject("brandName").field("type", "keyword").field("store", "yes").endObject();
builder.startObject("cateName").field("type", "keyword").field("store", "yes").endObject();
builder.startObject("cateNameTree").field("type", "keyword").field("store", "yes").endObject();
builder.startObject("salesPromotionTag").field("type", "keyword").field("store", "yes").endObject(); //促销标签 builder.startObject("perfumeType").field("type", "keyword").field("index", "no").field("store", "yes").endObject();
builder.startObject("brandScope").field("type", "keyword").field("index", "no").field("store", "yes").endObject(); /* float */
builder.startObject("volume").field("type", "float").field("store", "yes").endObject();
builder.startObject("originalPrice").field("type", "float").field("store", "yes").endObject();
builder.startObject("discount").field("type", "float").field("store", "yes").endObject(); /* date */
builder.startObject("gmtCreate").field("type", "date").field("store", "yes").endObject();
builder.startObject("gmtModified").field("type", "date").field("store", "yes").endObject(); /* suggester */
builder.startObject("suggestName").field("type","completion").endObject();
// builder.startObject("suggestBrandZhName").field("type","completion").field("analyzer","ik_max_word")
// .field("search_analyzer","ik_max_word").endObject(); //结束
builder.endObject().endObject().endObject(); PutMappingRequest mapping = Requests.putMappingRequest(index)
.type(type).source(builder);
client.admin().indices().putMapping(mapping).actionGet(); } /**
* 全量更新商品索引任务,凌晨4点执行
* @author chenxu
*
**/
@Scheduled(cron = "0 0 4 * * ?")
@ResponseBody
@RequestMapping(value = "/search/index/allproduct", method = RequestMethod.GET)
public void indexProducts(){
Timestamp updateTime = new Timestamp(0);
saveTimestamp(_PRODUCT_INDEX_TIME_KEY, new Timestamp(System.currentTimeMillis()));
productIndexService.createIndex(updateTime);
} /**
* 增量更新商品索引 ,每隔5分钟执行
* @author chenxu
*
**/
@Scheduled(cron = "0 */5 * * * ?")
@ResponseBody
@RequestMapping(value = "/search/index/product", method = RequestMethod.GET)
public void indexProduct() {
Timestamp updateTime = getTimestamp(_PRODUCT_INDEX_TIME_KEY);
long currentTimeMillis = System.currentTimeMillis();
productIndexService.createIndex(updateTime);
saveTimestamp(_PRODUCT_INDEX_TIME_KEY, new Timestamp(currentTimeMillis));
} private static Timestamp getTimestamp(String name) {
Timestamp timestamp = null;
try {
Jedis jedis = JedisClient.getJedis();
jedis.select(1);
String timestr = jedis.hget(_REDIS_DB_STORE_TIME_KEY_NAME, name);
JedisClient.returnResource(jedis);
if (StringUtils.isNotBlank(timestr)) {
timestamp = Timestamp.valueOf(timestr);
} else {
timestamp = new Timestamp(0);
}
} catch (Exception e) {
logger.error("elasticsearch获取索引最新更新时间失败,检查存储redis是否出现问题", e);
timestamp = new Timestamp(System.currentTimeMillis());
}
return timestamp;
} private void saveTimestamp(String name, Timestamp timestamp) {
try {
Jedis jedis = JedisClient.getJedis();
jedis.select(1);
jedis.hset(_REDIS_DB_STORE_TIME_KEY_NAME, name, timestamp.toString());
JedisClient.returnResource(jedis);
} catch (Exception e) {
logger.error("存储索引最新更新时间失败,检查存储redis是否出现问题", e);
}
} public static void main(String[] args) {
Settings settings = Settings.builder()
.put("cluster.name", "showjoy-shop-search")
.put("client.transport.sniff", true)
.build(); TransportClient tc = new PreBuiltTransportClient(settings);
try { tc.addTransportAddress(
new InetSocketTransportAddress(InetAddress.getByName("192.168.0.124"), 9300)); createMapping("item_index", "shop_item", tc);
// 去数据库中扫描达人店商品的待搜索字段
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// Map<String, Object> source = new HashMap<String, Object>();
// source.put("name", "酒");
// source.put("cateId", 5);
// source.put("brandId", 15);
// source.put("salesVolume", 250);
// source.put("price", 55.00d);
// source.put("income", 5.5d);
// source.put("createDate", sdf.format(new Date()));
//
// // 增加
// IndexResponse addResponse = tc
// .prepareIndex("item_index", "shop_item", "1")
// .setSource(source).get();
//
// if (addResponse != null
// && addResponse.getShardInfo().getSuccessful() == 1) {
// if (Result.CREATED.equals(addResponse.getResult())) {
// System.err.println("create success");
// } else {
// System.err.println("update success");
// }
// } else {
// System.err.println(JSON.toJSONString(addResponse));
// } } catch (Exception e) {
e.printStackTrace();
}
if (tc != null) {
tc.close();
} System.err.println("finished");
}
}

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

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