Elasticsearch教程---Document APIs(七)

9.1 新建文档

当我们索引一个文档, 怎么确认我们正在创建一个完全新的文档,而不是覆盖现有的呢?
请记住, _index_type_id 的组合可以唯一标识一个文档。所以,确保创建一个新文档的最简单办法是,使用索引请求的 POST 形式让 Elasticsearch 自动生成唯一 _id

JAVA代码示例1(_id自动生成):com.javablog.elasticsearch.document.impl.DocServiceImpl

@Override
public void add(String index,String type,String json) throws IOException {
    IndexRequest indexRequest = new IndexRequest(index, type);
    indexRequest.source(json, XContentType.JSON);
    IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
    log.debug("add: " + JSON.toJSONString(indexResponse));
}

JAVA代码示例1(指定_id值):com.javablog.elasticsearch.document.impl.DocServiceImpl

@Override
public void add(String index,String type,String json,String id) throws IOException {
    IndexRequest indexRequest = new IndexRequest(index, type, id);
    indexRequest.source(json, XContentType.JSON);
    IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
    log.debug("add: " + JSON.toJSONString(indexResponse));
}

9.2 更新文档

JAVA代码示例:com.javablog.elasticsearch.document.impl.DocServiceImpl

public UpdateResponse update(String index,String type,Map<String, Object> map,String id) throws IOException {
    UpdateRequest request = new UpdateRequest(index,type,id).doc(map);
    UpdateResponse updateResponse = restHighLevelClient.update(request, RequestOptions.DEFAULT);
    log.debug("update: " + JSON.toJSONString(updateResponse));
    return updateResponse;
}

9.3 删除文档

JAVA代码示例:com.javablog.elasticsearch.document.impl.DocServiceImpl

  /**
     * 删除
     * @param indexName 索引名称
     * @param typeName TYPE名称
     * @param docId    文档ID
     * @throws IOException
     */
    @Override
    public void deleteDocWithId(String indexName, String typeName, String docId) throws IOException {
        DeleteRequest request = new DeleteRequest(
                indexName,
                typeName,
                docId);
        DeleteResponse response = restHighLevelClient.delete(request, RequestOptions.DEFAULT);
        System.out.println(response+""+response.getResult());
    }

9.4 批量操作

9.4.1 批量增加与修改

JAVA代码示例:com.javablog.elasticsearch.document.impl.DocServiceImpl

   /**
     *  批量增加与修改
     * @param indexName 索引名称
     * @param typeName  TYPE名称
     * @param BulkRequest 批量请求
     * @throws IOException
     */
    @Override
    public BulkResponse bulkUpdateOrInsertDoc(String indexName, String typeName, BulkRequest builder) throws IOException {
        BulkResponse bulkResponse = restHighLevelClient.bulk(builder, RequestOptions.DEFAULT);
        return bulkResponse;
    }

请求串拼接:

BulkRequest bulkRequestBuilder = new BulkRequest();
bulkRequestBuilder.add(new IndexRequest(indexName, type, String.valueOf(100)).source(JSON.toJSONString(smsSendLog1), XContentType.JSON));
bulkRequestBuilder.add(new IndexRequest(indexName, type, String.valueOf(101)).source(JSON.toJSONString(smsSendLog2), XContentType.JSON));
BulkResponse bulkResponse = docService.bulkUpdateOrInsertDoc(indexName, type, bulkRequestBuilder);
        BulkItemResponse[] bulkItemResponseArr = bulkResponse.getItems();
        for (BulkItemResponse bulkItemResponse :bulkItemResponseArr) {
            System.out.println("操作是否失败:"+ bulkItemResponse.isFailed() + " 文档版本:" + bulkItemResponse.getVersion());
        }

9.4.2 批量删除

/**
 *  批量删除
 * @param indexName 索引名称
 * @param typeName  TYPE名称
 * @param docIdArr _ID数组
 * @throws IOException
 */
@Override
public void bulkDeleteDoc(String indexName, String typeName, String[] docIdArr) throws IOException {
    BulkRequest  bulkRequestBuilder = new BulkRequest();
    for (String docId : docIdArr) {
        bulkRequestBuilder.add(new DeleteRequest(indexName, typeName,docId));
    }
    BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequestBuilder, RequestOptions.DEFAULT);
    log.info(bulkResponse.toString());
}

9.6 refresh

一个理想的搜索解决方案中,新索引的数据应该能立即搜索到。ElasticSearch给人的第一印象仿佛就是如此工作的,即使是在多服务器环境下,然而事实并非如此(至少不是任何场景都能保证新索引的数据能被实时检索到)。

elasticsearch是基于lucene的,lucene是可以做到实时的,就是创建索引之后,立即能查询到。但是这样,要么是牺牲索引的效率,每次都索引之后都刷新,要么就是牺牲查询的效率每次查询之前都进行刷新。

无论哪一种,都会让你的性能下降10倍以上,所以只能采取一种折中的方案,每隔n秒自动刷新,这样你创建索引之后,最多在ns之内肯定能查到。这就是所谓的准实时(near real-time)查询。

elasticsearch默认刷新时间是1s。

刷新索引方法:

@Override
public void refresh(String indexName) throws IOException {
    RefreshRequest refreshRequest = new RefreshRequest(indexName);
    RefreshResponse refresh = restHighLevelClient.indices().refresh(refreshRequest, RequestOptions.DEFAULT);
    log.info(refresh.toString());
}

9.7 测试用例(老师逐个演示讲解)

演示用例:com.javablog.elasticsearch.test.document.DocServiceTest

package com.javablog.elasticsearch.test.document;

import com.alibaba.fastjson.JSON;
import com.javablog.elasticsearch.SearchServiceApplication;
import com.qianjavablogeng.elasticsearch.document.DocService;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import javax.tools.Tool;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = SearchServiceApplication.class)
@WebAppConfiguration
public class DocServiceTest {
    private final static Logger log = LoggerFactory.getLogger(DocServiceTest.class);
    private String indexName = "sms-logs-index";
    private String type = "sms_logs_type";
    @Autowired
    private DocService docService;

    /**
     * SMS_LOG_SUBMIT表
     * numSeqID 唯一ID
     * createDate 创建时间
     * longCode 发送的长号码
     * mobile 下发手机号
     * corpName 发送公司名称
     * smsContent 下发短信内容
     * state 短信下发状态  0 成功 1 失败
     * operatorId  '运营商编号  1 移动 2 联通 3 电信
     * province 省份
     * ipAddr 下发服务器IP地址
     * replyTotal 短信状态报告返回时长(秒)
     */
    @Test
    public void testAddData() throws IOException {
        int total = 10;
        SmsSendLog smsSendLog = new SmsSendLog();
        smsSendLog.setMobile("13800000000");
        smsSendLog.setCorpName("途虎养车");
        smsSendLog.setCreateDate(new Date());
        smsSendLog.setSendDate(new Date());
        smsSendLog.setIpAddr("10.126.2.9");
        smsSendLog.setLongCode("10690000988");
        smsSendLog.setReplyTotal(10);
        smsSendLog.setSmsContent("【途虎养车】亲爱的张三先生/女士,您在途虎购买的货品(单号TH123456)已到指定安装店多日," +
                "现需与您确认订单的安装情况,请点击链接按实际情况选择(此链接有效期为72H)。您也可以登录途虎APP进入" +
                "“我的-待安装订单”进行预约安装。若您在服务过程中有任何疑问,请致电400-111-8868向途虎咨询。");
        smsSendLog.setProvince("北京");
        smsSendLog.setOperatorId(1);
        smsSendLog.setFee(3);
        docService.add(indexName,type, JSON.toJSONString(smsSendLog),"1");

        smsSendLog.setMobile("13700000001");
        smsSendLog.setProvince("上海");
        smsSendLog.setSmsContent("【途虎养车】亲爱的刘红先生/女士,您在途虎购买的货品(单号TH1234526)已到指定安装店多日," +
                "现需与您确认订单的安装情况,请点击链接按实际情况选择(此链接有效期为72H)。您也可以登录途虎APP进入" +
                "“我的-待安装订单”进行预约安装。若您在服务过程中有任何疑问,请致电400-111-8868向途虎咨询。");
        docService.add(indexName,type, JSON.toJSONString(smsSendLog),"2");

        SmsSendLog smsSendLog1 = new SmsSendLog();
        smsSendLog1.setMobile("13100000000");
        smsSendLog1.setCorpName("盒马鲜生");
        smsSendLog1.setCreateDate(new Date());
        smsSendLog1.setSendDate(new Date());
        smsSendLog1.setIpAddr("10.126.2.9");
        smsSendLog1.setLongCode("10660000988");
        smsSendLog1.setReplyTotal(15);
        smsSendLog1.setSmsContent("【盒马】您尾号12345678的订单已开始配送,请在您指定的时间收货不要走开哦~配送员:" +
                "刘三,电话:13800000000");
        smsSendLog1.setProvince("北京");
        smsSendLog1.setOperatorId(2);
        smsSendLog1.setFee(5);
        docService.add(indexName,type, JSON.toJSONString(smsSendLog1),"3");

        smsSendLog1.setMobile("18600000001");
        smsSendLog1.setProvince("上海");
        smsSendLog1.setSmsContent("【盒马】您尾号7775678的订单已开始配送,请在您指定的时间收货不要走开哦~配送员:" +
                "王五,电话:13800000001");
        docService.add(indexName,type, JSON.toJSONString(smsSendLog1),"4");

        SmsSendLog smsSendLog2 = new SmsSendLog();
        smsSendLog2.setMobile("15300000000");
        smsSendLog2.setCorpName("滴滴打车");
        smsSendLog2.setCreateDate(new Date());
        smsSendLog2.setSendDate(new Date());
        smsSendLog2.setIpAddr("10.126.2.8");
        smsSendLog2.setLongCode("10660000988");
        smsSendLog2.setReplyTotal(50);
        smsSendLog2.setSmsContent("【滴滴单车平台】专属限时福利!青桔/小蓝月卡立享5折,特惠畅骑30天。" +
                "戳 https://xxxxxx退订TD");
        smsSendLog2.setProvince("上海");
        smsSendLog2.setOperatorId(3);
        smsSendLog2.setFee(7);
        docService.add(indexName,type, JSON.toJSONString(smsSendLog2),"5");

        smsSendLog2.setMobile("18000000001");
        smsSendLog2.setProvince("武汉");
        smsSendLog2.setSmsContent("【滴滴单车平台】专属限时福利!青桔/小蓝月卡立享5折,特惠畅骑30天。" +
                "戳 https://xxxxxx退订TD");
        docService.add(indexName,type, JSON.toJSONString(smsSendLog2),"6");

        SmsSendLog smsSendLog3 = new SmsSendLog();
        smsSendLog3.setMobile("13900000000");
        smsSendLog3.setCorpName("招商银行");
        smsSendLog3.setCreateDate(new Date());
        smsSendLog3.setSendDate(new Date());
        smsSendLog3.setIpAddr("10.126.2.8");
        smsSendLog3.setLongCode("10690000988");
        smsSendLog3.setReplyTotal(50);
        smsSendLog3.setSmsContent("【招商银行】尊贵的李四先生,恭喜您获得华为P30 Pro抽奖资格,还可领100元打" +
                "车红包,仅限1天");
        smsSendLog3.setProvince("上海");
        smsSendLog3.setOperatorId(1);
        smsSendLog3.setFee(8);
        docService.add(indexName,type, JSON.toJSONString(smsSendLog3),"7");

        smsSendLog3.setMobile("13990000001");
        smsSendLog3.setProvince("武汉");
        smsSendLog3.setSmsContent("【招商银行】尊贵的李四先生,恭喜您获得华为P30 Pro抽奖资格,还可领100元打" +
                "车红包,仅限1天");
        docService.add(indexName,type, JSON.toJSONString(smsSendLog3),"8");

        SmsSendLog smsSendLog4 = new SmsSendLog();
        smsSendLog4.setMobile("13700000000");
        smsSendLog4.setCorpName("中国平安保险有限公司");
        smsSendLog4.setCreateDate(new Date());
        smsSendLog4.setSendDate(new Date());
        smsSendLog4.setIpAddr("10.126.2.8");
        smsSendLog4.setLongCode("10690000998");
        smsSendLog4.setReplyTotal(18);
        smsSendLog4.setSmsContent("【中国平安】奋斗的时代,更需要健康的身体。中国平安为您提供多重健康保障,在奋斗之路上为您保驾护航。退订请回复TD");
        smsSendLog4.setProvince("武汉");
        smsSendLog4.setOperatorId(1);
        smsSendLog4.setFee(5);
        docService.add(indexName,type, JSON.toJSONString(smsSendLog4),"9");

        SmsSendLog smsSendLog5 = new SmsSendLog();
        smsSendLog5.setMobile("13600000000");
        smsSendLog5.setCorpName("中国移动");
        smsSendLog5.setCreateDate(new Date());
        smsSendLog5.setSendDate(new Date());
        smsSendLog5.setIpAddr("10.126.2.8");
        smsSendLog5.setLongCode("10650000998");
        smsSendLog5.setReplyTotal(60);
        smsSendLog5.setSmsContent("【北京移动】尊敬的客户137****0000,5月话费账单已送达您的139邮箱," +
                "点击查看账单详情 http://y.10086.cn/\n" +
                " 回Q关闭通知,关注“中国移动139邮箱”微信随时查账单【中国移动 139邮箱】");
        smsSendLog5.setProvince("武汉");
        smsSendLog5.setOperatorId(1);
        smsSendLog5.setFee(4);

        docService.add(indexName,type, JSON.toJSONString(smsSendLog5),"10");
    }

    /**
     * 单个删除
     * @throws IOException
     */
    @Test
    public void testDelDoc() throws IOException {
        //DOCID从增加日志中取或从图形界面中找
        docService.deleteDocWithId(indexName,type,"10");
    }

    /**
     * 删除多个
     * @throws IOException
     */
    @Test
    public void testBulkDeleteDoc() throws IOException {
        //DOCID从增加日志中取或从Kibana图形界面中找
        String[] docidArr =new String[]{"9","10"};
        docService.bulkDeleteDoc(indexName,type, docidArr);
    }

    /** 注意:
     * 虽然刷新比提交更轻量,但是它依然有消耗。人工刷新在测试写的时有用,但是不要在生产环境中每写一次就执行刷新,
     * 这会影响性能。
     * 相反,你的应用需要意识到ES近实时搜索的本质,并且容忍它。
     */
    /**
     * 不是所有的用户都需要每秒刷新一次。也许你使用ES索引百万日志文件,你更想要优化索引的速度,而不是进实时搜索。
     * 你可以通过修改配置项refresh_interval减少刷新的频率:1
     PUT /my_logs
     {
     "settings": {
     "refresh_interval": "30s" <1>
     }
     }
     */
    @Test
    public void testRefresh() throws IOException {
        long docSize1 = docService.countDoc(indexName, type);
        SmsSendLog smsSendLog5 = new SmsSendLog();
        smsSendLog5.setMobile("13600000000");
        smsSendLog5.setCorpName("中国移动");
        smsSendLog5.setCreateDate(new Date());
        smsSendLog5.setSendDate(new Date());
        smsSendLog5.setIpAddr("10.126.2.8");
        smsSendLog5.setLongCode("10690000998");
        smsSendLog5.setReplyTotal(30);
        smsSendLog5.setSmsContent("【中国移动】尊敬的客户137****0000,您的话费不足10元,为了不影响您的使用请尽快充值。");
        smsSendLog5.setProvince("武汉");
        smsSendLog5.setOperatorId(1);
        smsSendLog5.setFee(5);
        docService.add(indexName,type, JSON.toJSONString(smsSendLog5),"8");
        long docSize2 = docService.countDoc(indexName, type);
        System.out.println("docSize1:" + docSize1 + " docSize2:" + docSize2 + " 因为没有刷新,docSize1 == docSize2");

        long docSize3 = docService.countDoc(indexName, type);
        SmsSendLog smsSendLog6 = new SmsSendLog();
        smsSendLog6.setMobile("13600000000");
        smsSendLog6.setCorpName("中国移动");
        smsSendLog6.setCreateDate(new Date());
        smsSendLog6.setSendDate(new Date());
        smsSendLog6.setIpAddr("10.126.2.8");
        smsSendLog6.setLongCode("10690000998");
        smsSendLog6.setReplyTotal(60);
        smsSendLog6.setSmsContent("【中国移动】为了答谢老用户,近期展开充话费,送流量的活动,充的越多,送的越多,详情请见http://xxxxxxxxxxxxxxxxxx");
        smsSendLog6.setProvince("武汉");
        smsSendLog6.setOperatorId(1);
        smsSendLog6.setFee(9);
        docService.add(indexName,type, JSON.toJSONString(smsSendLog6),"9");
        //刷新
        docService.refresh(indexName);
        long docSize4 = docService.countDoc(indexName, type);
        System.out.println("docSize3:" + docSize3 + " docSize4:" + docSize4 + " 因为有刷新,docSize3 =! docSize4");
    }

    //修改
    @Test
    public void testUpdateDoc() throws IOException {
        //2.插入一个id为10的文档
        SmsSendLog smsSendLog6 = new SmsSendLog();
        smsSendLog6.setMobile("13200000000");
        smsSendLog6.setCorpName("泰康人寿");
        smsSendLog6.setCreateDate(new Date());
        smsSendLog6.setSendDate(new Date());
        smsSendLog6.setIpAddr("10.126.2.8");
        smsSendLog6.setLongCode("10690000998");
        smsSendLog6.setReplyTotal(10);
        smsSendLog6.setSmsContent("【泰康人寿】邀请函:公司举办客服节活动,免费赠送口腔检查券,以及价值2680元的指纹密码锁,高端候鸟医养结合社区体验券。了解回复Y,退订回T");
        smsSendLog6.setProvince("武汉");
        smsSendLog6.setOperatorId(1);
        smsSendLog6.setFee(6);
        docService.add(indexName,type, JSON.toJSONString(smsSendLog6),"10");

        //3.更新这个文档 age改为18
        Map<String,Object> map =new HashMap<>();
        map.put("province","天津");
        map.put("replyTotal",100);
        UpdateResponse update = docService.update(indexName, type, map, "10");
    }


    //批量增加文档
    @Test
    public void testBuldInsertDoc() throws IOException {
        BulkRequest bulkRequestBuilder = new BulkRequest();
        SmsSendLog smsSendLog5 = new SmsSendLog();
        smsSendLog5.setMobile("13500000000");
        smsSendLog5.setCorpName("京东");
        smsSendLog5.setCreateDate(new Date());
        smsSendLog5.setSendDate(new Date());
        smsSendLog5.setIpAddr("10.126.2.8");
        smsSendLog5.setLongCode("10690000998");
        smsSendLog5.setReplyTotal(30);
        smsSendLog5.setSmsContent("【京东金融】尊敬的用户,您的20元信用卡还款券还未领取,为避免奖励过期造成" +
                "无法领取的情况,请及时领取  (已领请忽略)!回N退订");
        smsSendLog5.setProvince("北京");
        smsSendLog5.setOperatorId(1);
        smsSendLog5.setFee(6);

        SmsSendLog smsSendLog6 = new SmsSendLog();
        smsSendLog6.setMobile("13600000000");
        smsSendLog6.setCorpName("京东");
        smsSendLog6.setCreateDate(new Date());
        smsSendLog6.setSendDate(new Date());
        smsSendLog6.setIpAddr("10.126.2.8");
        smsSendLog6.setLongCode("10690000998");
        smsSendLog6.setReplyTotal(60);
        smsSendLog6.setSmsContent("【京东】PLUS会员上线京典卡、联名卡双卡种!开通京典卡,享10倍返利、" +
                "360元运费券/年等特权;开通联名卡,还可额外享爱奇艺VIP年卡、知乎读书会员。7月8号PLUS DAY,PLUS下单" +
                "还可赢免单,回复BK退订");
        smsSendLog6.setProvince("武汉");
        smsSendLog6.setOperatorId(1);
        smsSendLog6.setFee(6);

        bulkRequestBuilder.add(new IndexRequest(indexName, type, String.valueOf(100)).source(JSON.toJSONString(smsSendLog5), XContentType.JSON));
        bulkRequestBuilder.add(new IndexRequest(indexName, type, String.valueOf(101)).source(JSON.toJSONString(smsSendLog6), XContentType.JSON));

        BulkResponse bulkResponse = docService.bulkUpdateOrInsertDoc(indexName, type, bulkRequestBuilder);
        BulkItemResponse[] bulkItemResponseArr = bulkResponse.getItems();
        for (BulkItemResponse bulkItemResponse :bulkItemResponseArr) {
            System.out.println("操作是否失败:"+ bulkItemResponse.isFailed() + " 文档版本:" + bulkItemResponse.getVersion());
        }
    }

    //批量更新这个文档
    @Test
    public void testBuldUpdateDoc() throws IOException {
        //5.批量更新这个文档
        BulkRequest bulkRequestBuilder = new BulkRequest();
        for (int i = 100;i <= 101;i++) {
            Map<String,Object> maps =new HashMap<>();
            maps.put("province","天津");
            maps.put("replyTotal",120);
            bulkRequestBuilder.add(new UpdateRequest(indexName, type, String.valueOf(i)).doc(maps));
        }
        BulkResponse bulkResponse = docService.bulkUpdateOrInsertDoc(indexName, type, bulkRequestBuilder);
        BulkItemResponse[] bulkItemResponseArr = bulkResponse.getItems();
        for (BulkItemResponse bulkItemResponse :bulkItemResponseArr) {
            System.out.println("操作是否失败:"+ bulkItemResponse.isFailed() + " 文档版本:" + bulkItemResponse.getVersion());
        }
    }
}

完整代码:https://github.com/chutianmen/elasticsearch-examples

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值