package com.itstar.elasticsearch_test1;
/**
 * ES API操作
 * @author ASUS
 *
 */
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetItemResponse;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
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.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.junit.Before;
import org.junit.Test;
public class ESTest_1 {
    // 对ES的操作都是通过client
    private TransportClient client;
    // 注意:加注解才能运行
    @SuppressWarnings("unchecked")
    @Before
    // @Before 以后在操作ES的时候首先获取连接-初始化Client
    // 获取连接-初始化Client
    public void getClient() throws Exception {
        // 1.设置连接集群的名称
        Settings settings = Settings.builder().put("cluster.name", "my-application").build();
        // 2.连接集群
        client = new PreBuiltTransportClient(settings);
        // IP,client-客户机操作ES的端口号
        client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.212.111"), 9300));
    }
    // 一、创建索引和删除索引
    @Test
    public void createIndex_blog() {
        client.admin().indices().prepareCreate("blog1").get();
        // 关掉连接
        client.close();
    }
    @Test
    public void deleteIndex() {
        client.admin().indices().prepareDelete("blog").get();
        // 关掉连接
        client.close();
    }
    // 二、新建文档--使用json
    @Test
    public void createDocByJson() {
        // 使用json创建Document
        String json = "{" + "\"id\":\"1\"," + "\"title\":\"基于Lucene的搜索服务器\","
                + "\"content\":\"它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口\"" + "}";
        // 创建文档
        // 注意:这里面的参数id-"1"是ES的ID,和上面的"id"-Json串里的id 不是一个ID
        IndexResponse indexResponse = client.prepareIndex("blog", "article", "1").setSource(json).execute().actionGet();
        // 打印返回结果
        System.out.println("index:" + indexResponse.getIndex());
        System.out.println("type:" + indexResponse.getType());
        System.out.println("id:" + indexResponse.getId());
        System.out.println("version:" + indexResponse.getVersion());
        System.out.println("result:" + indexResponse.getResult());
        // 关闭连接
        client.close();
    }
    // 三、新建文档--使用map
    @Test
    public void createDocByMap() {
        // 源数据map构建器添加json
        Map<String, Object> json = new HashMap<String, Object>();
        json.put("id", "2");
        json.put("title", "基于Lucene的搜索服务器");
        json.put("content", "它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口");
        // 创建文档
        // 注意:这里没有传第三个数-ID,但是ES依然会自动产生ID的
        IndexResponse indexResponse = client.prepareIndex("blog", "article").setSource(json).execute().actionGet();
        // 打印返回结果
        System.out.println("index:" + indexResponse.getIndex());
        System.out.println("type:" + indexResponse.getType());
        System.out.println("id:" + indexResponse.getId());
        System.out.println("version:" + indexResponse.getVersion());
        System.out.println("result:" + indexResponse.getResult());
        // 关闭连接
        client.close();
    }
    // 四、新建文档--使用es
    @Test
    public void createDocByXContent() throws Exception {
        // 源数据es构建器添加json
        XContentBuilder builder = XContentFactory.jsonBuilder().startObject().field("id", 5)
                .field("title", "基于Lucene的搜索服务器").field("content", "它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口").endObject();
        // 创建文档
        // 注意:这里没有传第三个数-ID,但是ES依然会自动产生ID的
        IndexResponse indexResponse = client.prepareIndex("blog", "article").setSource(builder).execute().actionGet();
        // 打印返回结果
        System.out.println("index:" + indexResponse.getIndex());
        System.out.println("type:" + indexResponse.getType());
        System.out.println("id:" + indexResponse.getId());
        System.out.println("version:" + indexResponse.getVersion());
        System.out.println("result:" + indexResponse.getResult());
        // 关闭连接
        client.close();
    }
    // 五、查询文档-单个索引
    @Test
    public void getData() {
        // 注意:指定的id要存在-得是之前创建过的id-ES的id
        GetResponse response = client.prepareGet("blog", "article", "1").get();
        System.out.println(response.getSourceAsString());
        client.close();
    }
    // 六、查询文档-多个索引
    @Test
    public void getMultiData() {
        MultiGetResponse multiResponse = client.prepareMultiGet().add("blog", "article", "1")
                .add("blog", "article", "1", "UnrO63MBy_Mwy4r5J6VY").add("blog", "article", "Rw3d8XMBfpkCch_aW3Da")
                .get();
        // 遍历返回的结果
        for (MultiGetItemResponse response : multiResponse) {
            GetResponse getResponse = response.getResponse();
            if (getResponse.isExists()) {
                String sourceAsString = getResponse.getSourceAsString();
                System.out.println(sourceAsString);
            }
        }
        client.close();
    }
    // 七、更新文档-update
    @Test
    public void updateData() throws Exception {
        // 创建更新数据的请求对象
        UpdateRequest updateRequest = new UpdateRequest();
        updateRequest.index("blog");
        updateRequest.type("article");
        updateRequest.id("Rw3d8XMBfpkCch_aW3Da");
        updateRequest.doc(XContentFactory.jsonBuilder().startObject()
                // 对没有的字段添加, 对已有的字段替换
                .field("title", "基于Lucene的搜索服务器").field("content", "它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。大数据前景无限")
                .field("createDate", "2017-8-22").endObject());
        UpdateResponse indexResponse = client.update(updateRequest).get();
        // 打印返回结果
        System.out.println("index:" + indexResponse.getIndex());
        System.out.println("type:" + indexResponse.getType());
        System.out.println("id:" + indexResponse.getId());
        System.out.println("version:" + indexResponse.getVersion());
        System.out.println("result:" + indexResponse.getResult());
        // 关闭连接
        client.close();
    }
    // 八、更新文档-upsert
    @Test
    public void updateOrInsertData() throws Exception {
        // 设置查询条件, 查找不到("blog", "article", "5")则添加
        IndexRequest indexRequest = new IndexRequest("blog", "article", "5")
                .source(XContentFactory.jsonBuilder().startObject().field("title", "基于Lucene的搜索服务器")
                        .field("content", "它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。大数据前景无限").endObject());
        // 设置更新, 查找("blog", "article", "5")就更新下面的设置
        UpdateRequest upsert = new UpdateRequest("blog", "article", "5")
                .doc(XContentFactory.jsonBuilder().startObject().field("user", "李四").endObject()).upsert(indexRequest);
        client.update(upsert).get();
        client.close();
    }
    // 九、删除数据-prepareDelete
    @Test
    public void deleteData() {
        // 1 删除文档数据
        DeleteResponse indexResponse = client.prepareDelete("blog", "article", "5").get();
        // 2 打印返回的结果
        System.out.println("index:" + indexResponse.getIndex());
        System.out.println("type:" + indexResponse.getType());
        System.out.println("id:" + indexResponse.getId());
        System.out.println("version:" + indexResponse.getVersion());
        System.out.println("found:" + indexResponse.getResult());
        // 3 关闭连接
        client.close();
    }
    // 十、查询所有--queryStringQuery
    @Test
    public void query() {
        // 类似于like,对所有字段like
        SearchResponse searchResponse = client.prepareSearch("blog").setTypes("article")
                .setQuery(QueryBuilders.queryStringQuery("大数据")).get();
        SearchHits hits = searchResponse.getHits();
        System.out.println("查询结果有:" + hits.getTotalHits() + " 条");
        for (SearchHit searchHits : hits) {
            System.out.println(searchHits.getSourceAsString());
        }
        client.close();
    }
    // 十一、词条查询-TermQuery
    // 注意:需要加入分词器,不然容易搜不到匹配的词
    @Test
    public void termQuery() {
        // 类似于MySQL中的=
        // 注意:这个=不是真正的=,它不是与字段等于,而是和字段的分词结果等于。
        SearchResponse searchResponse = client.prepareSearch("blog").setTypes("article")
                .setQuery(QueryBuilders.termQuery("content", "web")).get();
        SearchHits hits = searchResponse.getHits();
        System.out.println("查询结果有:" + hits.getTotalHits() + " 条");
        for (SearchHit searchHits : hits) {
            System.out.println(searchHits.getSourceAsString());
        }
        client.close();
    }
    // 十二、模糊查询-fuzzy
    // 注意:需要加入分词器,不然容易搜不到匹配的词
    @Test
    public void fuzzyQuery() {
        // 模糊查询
        SearchResponse searchResponse = client.prepareSearch("blog").setTypes("article")
                .setQuery(QueryBuilders.fuzzyQuery("content", "web")).get();
        SearchHits hits = searchResponse.getHits();
        System.out.println("查询结果有:" + hits.getTotalHits() + " 条");
        for (SearchHit searchHits : hits) {
            System.out.println(searchHits.getSourceAsString());
        }
        client.close();
    }
    // 十三、映射相关操作
    @Test
    public void createMapping() throws Exception {
        //1.设置mapping
        XContentBuilder builder = XContentFactory.jsonBuilder().startObject().startObject("article") // 表
                .startObject("properties").startObject("id1") // properties里面有id1
                .field("type", "text").field("store", "true").endObject().startObject("title2") // properties里面有title2
                .field("type", "text").field("store", "false").endObject().startObject("content3") // properties里面有content3
                .field("type", "text").field("store", "true").endObject().endObject().endObject().endObject();
        //2.添加mapping
        //注意:最好先新建一个索引-blog1,
        //      或者将id和title和content名字都改一下,否则会操作失败
        PutMappingRequest mappingRequest = Requests.putMappingRequest("blog1").type("article").source(builder);
        client.admin().indices().putMapping(mappingRequest).get();
        //3.关闭资源
        client.close();
    }
}