package com.ggj.java.firstdemo; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.HashMap; import java.util.List; import java.util.Map; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest; import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest; import org.elasticsearch.action.admin.indices.alias.get.GetAliasesResponse; import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequest; import org.elasticsearch.action.admin.indices.analyze.AnalyzeResponse; import org.elasticsearch.action.admin.indices.close.CloseIndexRequest; import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse; import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest; import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse; import org.elasticsearch.action.admin.indices.open.OpenIndexRequest; import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest; import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse; import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse; import org.elasticsearch.client.ClusterAdminClient; import org.elasticsearch.client.IndicesAdminClient; 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 lombok.extern.slf4j.Slf4j; /** * @author:gaoguangjin * @date 2016/10/24 15:29 */ @Slf4j public class CrudDemo { private static TransportClient client = null; //索引名称要小写 private static String INDEX_NAME = "elsdb"; private static String INDEX_ALIAS_NAME_VERSION_ONE = "elsdb_alis_v1"; private static String INDEX_ALIAS_NAME_ALIS = "elsdb_alis"; private static String INDEX_ALIAS_NAME_VERSION_TWO = "elsdb_alis_v2"; private static String TYPE_NAME = "tb_system"; private static String FIELD_NAME = "user_name"; static { try { Map<String, String> map = new HashMap(); // 基础名称 map.put("cluster.name", "my-application-A"); Settings.Builder settings = Settings.builder().put(map); client = TransportClient.builder().settings(settings).build() .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300)); } catch (UnknownHostException e) { log.error("init error:{}", e.getMessage()); } } public static void main(String[] args) { try { index(); //等待集群shard,防止No shard available for 异常 ClusterAdminClient clusterAdminClient = client.admin().cluster(); clusterAdminClient.prepareHealth().setWaitForYellowStatus().execute().actionGet(5000); // analyze(); } catch (Exception e) { log.error("main error:{}", e.getMessage()); }finally { client.close(); } } /** * ttp://localhost:9200/index/_analyze?text=做人如果没有梦想那和咸鱼有什么区别勒&analyzer=pinyin_analyzer * ttp://localhost:9200/index/_analyze?text=今天是个好天气啊&analyzer=ik_max_word */ private static void analyze() { IndicesAdminClient indicesAdminClient = client.admin().indices(); String analyzerName="pinyin"; String text="默认的拼音例子"; showAnaylzerText(indicesAdminClient,analyzerName,text); //自定义分析器必须要指定indexName,插件的就不用了 analyzerName="pinyin_analyzer"; text="做人如果没有梦想那和咸鱼有什么区别勒"; showAnaylzerText(indicesAdminClient,analyzerName,text); //官网的demo例子 analyzerName="my_analyzer"; text="The quick & brown fox is a dog"; showAnaylzerText(indicesAdminClient,analyzerName,text); //验证ik分词 analyzerName="ik_max_word"; text="好好学习天天向上!"; showAnaylzerText(indicesAdminClient,analyzerName,text); } private static void showAnaylzerText(IndicesAdminClient indicesAdminClient,String analyzerName, String text) { AnalyzeResponse analyzeResponse = indicesAdminClient.analyze(new AnalyzeRequest(INDEX_NAME).analyzer(analyzerName).text(text)).actionGet(); List<AnalyzeResponse.AnalyzeToken> token=analyzeResponse.getTokens(); for (AnalyzeResponse.AnalyzeToken analyzeToken : token) { log.info(analyzerName+": {}",analyzeToken.getTerm()); } } /** * http://es.xiaoleilu.com/010_Intro/25_Tutorial_Indexing.html * http://es.xiaoleilu.com/070_Index_Mgmt/05_Create_Delete.html * 索引相关的 */ private static void index() throws IOException, InterruptedException { // cluster(),产生一个允许从集群中执行action或操作的client; IndicesAdminClient indicesAdminClient = client.admin().indices(); //创建索引 if (checkExistsIndex(indicesAdminClient, INDEX_NAME)) { deleteIndex(indicesAdminClient, INDEX_NAME); } // String settings = getIndexSetting(); // CreateIndexResponse createIndexResponse = indicesAdminClient.prepareCreate(INDEX_NAME).setSettings(settings).execute().actionGet(); CreateIndexResponse createIndexResponse = indicesAdminClient.prepareCreate(INDEX_NAME).setSettings().execute().actionGet(); // log.info("创建索引{}:{}", INDEX_NAME, createIndexResponse.getContext()); //索引的相关配置操作 indexConfig(indicesAdminClient, INDEX_NAME); // indexMapping(indicesAdminClient, INDEX_NAME, TYPE_NAME); } /** * * @param indicesAdminClient * @param indexName * @param typeName * @throws IOException */ private static void indexMapping(IndicesAdminClient indicesAdminClient, String indexName, String typeName) throws IOException { //type就相当于表的 String typeSource=getIndexTypeSource(typeName,FIELD_NAME); //typetwo PutMappingRequest mapping = Requests.putMappingRequest(indexName).type(typeName).source("typeSource"); PutMappingResponse putMappingResponseTwo = indicesAdminClient.putMapping(mapping).actionGet(); } /** * DELETE /index_one,index_two * DELETE /index_* * 删除所有 * DELETE /_all * 删除索引 * * @param indicesAdminClient * @param indexName */ private static void deleteIndex(IndicesAdminClient indicesAdminClient, String indexName) { //删除索引 new DeleteIndexRequest("a","b") 支持多个 DeleteIndexResponse deleteIndexResponse = indicesAdminClient.delete(new DeleteIndexRequest(indexName)).actionGet(); log.info("删除索引{}:{}", indexName, deleteIndexResponse.getContext()); } /** * 索引的相关操作 * * @param indicesAdminClient * @param indexName * @throws IOException */ private static void indexConfig(IndicesAdminClient indicesAdminClient, String indexName) throws IOException { //settings 设置 String settings = getIndexSetting(); // PUT /my_temp_index/_settings updatesettings showIndexSettings(indicesAdminClient,indexName); UpdateSettingsResponse updateSettingsResponse = indicesAdminClient.prepareUpdateSettings(indexName).setSettings(settings).execute().actionGet(); log.info("更新 index setting:{}", updateSettingsResponse); //更新索引settings之前要关闭索引 indicesAdminClient.close(new CloseIndexRequest().indices(indexName)).actionGet(); //配置拼音自定义分析器 indicesAdminClient.prepareUpdateSettings(indexName).setSettings(getIndexPinYinSetting()).execute().actionGet(); //自定义分析器 indicesAdminClient.prepareUpdateSettings(indexName).setSettings(getIndexDemoSetting()).execute().actionGet(); //打开索引 indicesAdminClient.open(new OpenIndexRequest().indices(indexName)).actionGet(); //索引别名映射 createAliasIndex(indicesAdminClient); showIndexSettings(indicesAdminClient,indexName); } /** * 索引 别名 就像一个快捷方式或软连接,可以指向一个或多个索引,也可以给任何需要索引名的 API 使用。别名带给我们极大的灵活性, * 比如 我们线上使用一个索引名为index_a的结构,里面有一个类型现在不满足要求,现在需要修改,因为elasticsearch不支持直接修改类型,所以我们必须要重新建立一个新的索引 * 然后将久索引的数据拷贝过去。 但是如果让新的索引起作用,我们需要要修改引用代码,因为索引名称更换了,但是如果我们一开始创建索引的时候就给索引增加一个别名 * 使用的时候都是使用index_alis 无论软连接的指向是什么索引,对外暴露的始终都是index_alis * @param indicesAdminClient */ private static void createAliasIndex(IndicesAdminClient indicesAdminClient) { // 1 创建索引 elsdb_alis_v1。 // 2 将别名 elsdb_alis 指向 elsdb_alis_v1 // 3 然后,我们决定修改索引elsdb_alis_v1中一个字段的映射。当然我们不能修改现存的映射,索引我们需要重新索引数据。首先,我们创建有新的映射的索引 elsdb_alis_v2。 // 4 然后我们从将数据从 elsdb_alis_v1 迁移到 elsdb_alis_v2,下面的过程在【重新索引】中描述过了。一旦我们认为数据已经被正确的索引了,我们就将别名指向新的索引。 //创建索引 if (checkExistsIndex(indicesAdminClient, INDEX_ALIAS_NAME_VERSION_ONE)) { deleteIndex(indicesAdminClient, INDEX_ALIAS_NAME_VERSION_ONE); } indicesAdminClient.prepareCreate(INDEX_ALIAS_NAME_VERSION_ONE).setSettings().execute().actionGet(); //添加alias 所有别名 indicesAdminClient.prepareAliases().addAlias(INDEX_ALIAS_NAME_VERSION_ONE,INDEX_ALIAS_NAME_ALIS).execute().actionGet(); GetAliasesResponse getAliasesResponse = indicesAdminClient.getAliases(new GetAliasesRequest().indices(INDEX_ALIAS_NAME_ALIS)).actionGet(); //log.info("getAliasesResponse index setting:{}", getAliasesResponse.getAliases()); indicesAdminClient.prepareAliases().removeAlias(INDEX_ALIAS_NAME_VERSION_ONE,INDEX_ALIAS_NAME_ALIS).addAlias(INDEX_ALIAS_NAME_VERSION_TWO,INDEX_ALIAS_NAME_ALIS); } private static void showIndexSettings(IndicesAdminClient indicesAdminClient, String indexName) { GetSettingsResponse settingInfo = indicesAdminClient.getSettings(new GetSettingsRequest().indices(indexName)).actionGet(); // log.info("显示 index setting:{}", settingInfo.getIndexToSettings().get(indexName).getAsMap()); } private static boolean checkExistsIndex(IndicesAdminClient indicesAdminClient, String indexName) { return indicesAdminClient.prepareExists(indexName).execute().actionGet().isExists(); } /** number_of_shards 定义一个索引的主分片个数,默认值是 `5`。这个配置在索引创建后不能修改。 number_of_replicas 每个主分片的复制分片个数,默认是 `1`。这个配置可以随时在活跃的索引上修改。 * When changing the number of replicas the index needs to be open. Changing the number of replicas on a closed index might prevent the index to be opened correctly again. * @return * @throws IOException */ public static String getIndexSetting() throws IOException { //默认索引创建的分片数都是5 XContentBuilder mapping = XContentFactory.jsonBuilder() .startObject() //.field("number_of_shards", "5") .field("number_of_replicas", "1") .endObject(); return mapping.string(); } /** * https://github.com/medcl/elasticsearch-analysis-pinyin/tree/v1.7.5 * pinyin配置分析器 * @return */ public static String getIndexPinYinSetting() throws IOException { XContentBuilder mapping = XContentFactory.jsonBuilder() .startObject() .startObject("analysis") .startObject("analyzer") .startObject("pinyin_analyzer") .field("tokenizer", "my_pinyin") .array("filter","nGram","word_delimiter") .endObject() .endObject() .startObject("tokenizer") .startObject("my_pinyin") .field("type", "pinyin") .field("first_letter","prefix") .field("padding_char","") .endObject() .endObject() .endObject() .endObject(); return mapping.string(); } /** * 分析器 是三个顺序执行的组件的结合(字符过滤器,分词器,标记过滤器) * http://es.xiaoleilu.com/070_Index_Mgmt/20_Custom_Analyzers.html * @return */ public static String getIndexDemoSetting() throws IOException { XContentBuilder mapping = null; try { mapping = XContentFactory.jsonBuilder() .startObject() .startObject("analysis") //字符过滤器 .startObject("char_filter") .startObject("&_to_and") .field("type", "mapping") .field("mappings","&=> and") .endObject() .endObject() .startObject("filter") .startObject("my_stopwords") .field("type", "stop") .field("stopwords","the","a") .endObject() .endObject() //分析器 .startObject("analyzer") .startObject("my_analyzer") //自定义 .field("type", "custom") //用 html_strip 字符过滤器去除所有的 HTML 标签 .array("char_filter","html_strip","&_to_and") //使用 standard 分词器分割单词 .field("tokenizer", "standard") // 使用 lowercase 标记过滤器将词转为小写,stop 标记过滤器去除一些自定义停用词 .array("filter","lowercase","my_stopwords") .endObject() .endObject() .endObject() .endObject(); } catch (IOException e) { e.printStackTrace(); } return mapping.string(); } /** * { * "fulltext": { * "_all": { * "analyzer": "ik_max_word", * "search_analyzer": "ik_max_word", * "term_vector": "no", * "store": "false" * }, * "properties": { * "content": { * "type": "text", * "analyzer": "ik_max_word", * "search_analyzer": "ik_max_word", * "include_in_all": "true", * "boost": 8 * } * } * } * }' * * @param typeName * @return */ private static String getIndexTypeSource(String typeName, String fieldName) throws IOException { XContentBuilder mapping = XContentFactory.jsonBuilder() .startObject() // 索引库名(类似数据库中的表) .startObject(typeName) //匹配全部 //.startObject("_all").field("analyzer","ik_max_word").field("search_analyzer","ik_max_word").field("term_vector","no").field("store","false").endObject() .startObject("properties") //根据只对content这个Fields分词 .startObject(fieldName).field("type", "string").field("store", "no") .field("term_vector", "with_positions_offsets").field("analyzer", "ik_max_word") .field("search_analyzer", "ik_max_word").field("include_in_all", "true").field("boost", 8) .endObject() .endObject() .endObject() .endObject(); return mapping.string(); } }