分享好友

×
取消 复制
Elasticsearch使用ElasticsearchTemplate实现字段值增加/拼接字符串
2020-06-01 13:47:23

需求背景:当浏览文档时使此文档的浏览数+1;利用ElsaticSearch的脚本更新可以灵活的实现该需求

如果使用sql应对以上需求,我们应该很简单的就可以写出

update news_bak.newsBase set browseCount = browseCount + 1 where id="5bf29a4f086899caed65e6bc"

在es中对应以上sql逻辑的代码,如下

POST /news_bak/newsBase/5bf29a4f086899caed65e6bc/_update
 {
   "script": {
     "inline": "ctx._source.browseCount += params.incr",
     "params": {
       "incr":1
     }
   }
 }

其中,news_bak为对应的index,newsBase为对应的type. 另外,注意一点,在引用变量时,以前的版本直接引用变量名即可,而Elasticsearch5.0以上的版本取参数需要使用==params.{参数名}==,这是语法上的更新,如果跟以前一样,直接这样使用:

POST /news_bak/newsBase/5bf29a4f086899caed65e6bc/_update
 {
   "script": {
     "inline": "ctx._source.browseCount += incr",
     "params": {
       "incr":1
     }
   }
 }

则会报错,提示我们出现异常==illegal_argument_exception==,告诉我们原因是==Variable [incr] is not defined.==,参数 incr 未定义

{
  "error": {
    "root_cause": [
      {
        "type": "remote_transport_exception",
        "reason": "[Sn0hpRC][192.168.8.53:9300][indices:data/write/update[s]]"
      }
    ],
    "type": "illegal_argument_exception",
    "reason": "failed to execute script",
    "caused_by": {
      "type": "script_exception",
      "reason": "compile error",
      "script_stack": [
        "... x._source.browseCount += incr",
        "                             ^---- HERE"
      ],
      "script": "ctx._source.browseCount += incr",
      "lang": "painless",
      "caused_by": {
        "type": "illegal_argument_exception",
        "reason": "Variable [incr] is not defined."
      }
    }
  },
  "status": 400
}

所以我们需要注意一下自己的Elasticsearch==版本==

接下来是使用Spring的ElasticSearchTemplate来进行操作,方法以及进行了封装 主要代码如下: model:

@Document(indexName = "news_bak", type = "newsBase")
public class NewsBase implements Serializable {
    @Id
    private String id;

    private String author;

    private String browsingVolume;

    private String headImg;

    private String content;
    ... 下面省略

}

EsUtil里面封装了对应的方法

/**
 * 提供es的工具类
 *
 * @author neo_chen
 * @version Ver 1.0 2018/11/16 新增
 * @Package
 */
public class EsUtil {

    /**
     * 在es的对应字段上追加对应的值
     * @param id  要追加的文档的id
     * @param clazz 文档对应Class对象
     * @param addFiled 要追加的字段
     * @param addParam 要追加的值
     * @return UpdateQuery
     * @eg 给这个文档的browseCount字段值+1
     * POST /#{index}/#{type}/#{id}/_update
     *  {
     *    "script": {
     *      "inline": "ctx._source.browseCount += params.incr",
     *      "params": {
     *        "incr":1
     *      }
     *    }
     *  }
     */
    public static <T>UpdateQuery filedValueAdd(String id, Class<T> clazz, String addFiled, Object addParam) {
        //构建UpdataRequest对象
        UpdateRequest updateRequest = new UpdateRequest();
        //设置参数
        Map<String, Object> params = new HashMap<>();
        params.put("incr", addParam);
        //构架Script对象,这里注意是 org.elasticsearch.script.Script
        Script script = new Script(Script.DEFAULT_SCRIPT_TYPE, "painless", "ctx._source." + addFiled + " += params.incr", params);
        updateRequest.script(script);
        //构架UpdateQueryBuilder 对象
        UpdateQueryBuilder updateQueryBuilder = new UpdateQueryBuilder();
        //设置要修改的_id
        updateQueryBuilder.withId(id);
        //设置updateRequest对象
        updateQueryBuilder.withUpdateRequest(updateRequest);
        //设置 class 对象,其实这里用class对象就是要区实体类标注的 index 和 type 也可以直接设置index 和 type
        /*
        //可以替换成
        updateQueryBuilder.withIndexName("your index");
        updateQueryBuilder.withType("yourType");
        */
        updateQueryBuilder.withClass(clazz);
        UpdateQuery build = updateQueryBuilder.build();
        return build;
    }

}

调用:

@Service(value = "newsBaseService")
public class NewsBaseServiceImpl implements NewsBaseService {
    @Autowired
    private ElasticsearchTemplate esTemplate;
    @Override
    public Long incrBrowse(String id) throws Exception {
        // id 为要改变的资讯id,NewsBase.class类,要修改的字段为browseCount,在原来的基础上+1
        UpdateQuery build = EsUtil.filedValueAdd(id, NewsBase.class, "browseCount", 1);
        UpdateResponse update = esTemplate.update(build);
        return null;
    }

}

分享好友

分享这个小栈给你的朋友们,一起进步吧。

Elasticsearch
创建时间:2020-05-22 14:49:51
ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。我们建立一个网站或应用程序,并要添加搜索功能,但是想要完成搜索工作的创建是非常困难的。我们希望搜索解决方案要运行速度快,我们希望能有一个零配置和一个完全免费的搜索模式,我们希望能够简单地使用JSON通过HTTP来索引数据,我们希望我们的搜索服务器始终可用,我们希望能够从一台开始并扩展到数百台,我们要实时搜索,我们要简单的多租户,我们希望建立一个云的解决方案。因此我们利用Elasticsearch来解决所有这些问题及可能出现的更多其它问题。
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

技术专家

查看更多
  • 栈栈
    专家
猜你喜欢
戳我,来吐槽~