elasticsearch、redis、mongo 的原生API,spring-data的XXXtemplate API,继承XXXrepository接口的API使用总结

原生的TransportClient,JedisCluster,MongoClient的API操作比较接近底层, 比较接近命令式操作,但操作较麻烦。下面分别看看spring data的玩法 

  • ES部分:ElasticsearchTemplate 持有TransportClient的引用,对其装饰增强,简化结果集的处理,不必显示进行model的赋值,只需要传入model的clazz对象。而以继承ElasticsearchCrudRepository接口的方式类似JPA方式操作看似easy,也自动处理结果集但个人认为有以下弊端:它通过model注解指定要操作的索引,通过方法名或@query注解指定查询条件较复杂时不太适合,操。作较麻烦易出错,不适合不熟悉JPA的coder。推荐ElasticsearchTemplate 的API,三种姿势比较如下
添加依赖,一般情况只需要spring-boot-starter-data-elasticsearch
<!--要使用支持xpack的连接,不宜使用spring-boot-starter-data-elasticsearch自动配置-->
       <!-- <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
      </dependency>-->
         <dependency>
         <groupId>org.springframework.data</groupId>
         <artifactId>spring-data-elasticsearch</artifactId>
         <version>3.1.5.RELEASE</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.elasticsearch.client</groupId>
                     <artifactId>transport</artifactId>
                 </exclusion>
             </exclusions>
      </dependency>
         <dependency>
          <groupId>org.elasticsearch.plugin</groupId>
          <artifactId>x-pack-api</artifactId>
          <version>6.2.4</version>
      </dependency>
      <dependency>
   <groupId>org.elasticsearch.client</groupId>
   <artifactId>x-pack-transport</artifactId>
   <version>6.2.4</version>
</dependency>
      <dependency>
          <groupId>org.elasticsearch.client</groupId>
          <artifactId>transport</artifactId>
          <version>6.2.4</version>
      </dependency>
     <dependency>
          <groupId>org.elasticsearch</groupId>
          <artifactId>elasticsearch</artifactId>
          <version>6.2.4</version>
      </dependency>
ES连接配置类
@Configuration
public class EsClientConfiguration {
@Value("${es.clusterName}")
private String clusterName;
@Value("${es.userName}")
private String userName;
@Value("${es.userPwd}")
private String userPwd;
@Value("${es.clusterNodes}")
private String clusterNodes;
@Value("${es.caPath}")
private String caPath;
@Value("${es.esKey}")
private String esKey;
@Value("${es.certificate}")
private String certificate;
@Value("${es.SSLflag:true}")
private boolean SSLflag;
@Bean
public TransportClient transportClient() throws UnknownHostException {
    Settings settings = null;
         if (SSLflag) {
            settings = Settings.builder()
                        .put("cluster.name", clusterName)
                  .put("xpack.security.user", userName + ":" + userPwd)
                  .put("xpack.ssl.certificate_authorities", caPath)
                  .put("xpack.ssl.key", esKey)
                        .put("xpack.ssl.certificate",certificate )
                  .put("xpack.security.transport.ssl.enabled", "true").build();

         } else {
            settings = Settings.builder().put("cluster.name", clusterName)
                  .put("xpack.security.user", userName + ":" + userPwd)
                  .put("xpack.security.transport.ssl.enabled", "false").build();
         }

   TransportClient client = new PreBuiltXPackTransportClient(settings);
    String[] ip_port = clusterNodes.split(",");
    for (String s : ip_port) {
        String[] split = s.split(":");
        client.addTransportAddress(new TransportAddress(InetAddress.getByName(split[0]), Integer.parseInt(split[1])));
    }
    return client;
    }

    @Bean
   public ElasticsearchTemplate elasticsearchTemplate() throws UnknownHostException {
      return new ElasticsearchTemplate(transportClient());
   }
}
操作ES的三种姿势对比
@Service
public class SearchServiceImpl implements ISearchService {
    private static final Pattern isChineseRegex = Pattern.compile("[\u4E00-\u9FA5]{1}");
    private static final String commodityIndex = "mallt_XXXX";
    private static final String commodityIndexType = "mallt_XXXX";
    @Autowired
    TransportClient client;
    @Autowired
    ElasticsearchTemplate elasticsearchTemplate;
    @Autowired
    CommoditySearchRepository repository;
    
    @Override
    public JsonResult<PageData<SearchSuggestVO>> getSearchSuggest(String searchKey, int pageNum, int pageSize) {
        return searchSuggestV3(searchKey, pageNum, pageSize);

    }
    /**
     * @Description: 原生TransportClient API
     * @param
     * @return
     * @throws Exception
     * @author majun
     * @date 2019/3/18 11:49
     * @version 1.0
     */
    private JsonResult<PageData<SearchSuggestVO>> searchSuggestV1(String searchKey, int pageNum, int pageSize) {
        //构建postFilter查询条件
        BoolQueryBuilder filter = QueryBuilders.boolQuery();
        filter.must(new TermQueryBuilder("mallStatus", "7"));
        //构建query查询条件
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        if (isChineseRegex.matcher(searchKey).find()) {
            query.should(new WildcardQueryBuilder("commodityName", "*" + searchKey + "*").boost(10))
                    .should(new MatchPhraseQueryBuilder("commodityName.chinese", searchKey).boost(5));

        } else {
            searchKey = searchKey.toLowerCase();
            query.should(new WildcardQueryBuilder("commodityName.pinyin", "*" + searchKey + "*").boost(15))
                    .should(new PrefixQueryBuilder("keyWord.pinyin", searchKey).boost(10));
        }

        SearchRequestBuilder requestBuilder = client.prepareSearch(commodityIndex)
                .setTypes(commodityIndexType)
                .setQuery(query)
                .setPostFilter(filter)
                .setSize(10)
                .setFetchSource("commodityName", null);
        System.out.println(requestBuilder);
        SearchResponse response=requestBuilder.get();
        RestStatus esStatus = response.status();
        if (200 != esStatus.getStatus()) {
            return JsonResult.fail();
        }
        List<SearchSuggestVO> list = new ArrayList<>();
        SearchHits hits = response.getHits();
        for (SearchHit entry : hits) {
            String value = entry.getSourceAsMap().get("commodityName").toString();
            SearchSuggestVO vo = new SearchSuggestVO();
            vo.setCommodityName(value);
            list.add(vo);
        }

        PageData<SearchSuggestVO> data = new PageData<>();
        data.setTotalCount((int) hits.totalHits);
        data.setPageNum(pageNum);
        data.setPageSize(pageSize);
        data.setDataList(list);
        return JsonResult.success(data);
    }

  /**
     * @Description: 基于spring-data-elasticsearch的ElasticsearchTemplate的API
     * @param
     * @return
     * @throws Exception
     * @author majun
     * @date 2019/3/18 11:49
     * @version 1.0
     */
    private JsonResult<PageData<SearchSuggestVO>> searchSuggestV2(String searchKey, int pageNum, int pageSize) {
        //构建postFilter查询条件
        BoolQueryBuilder filter = QueryBuilders.boolQuery();
        filter.must(new TermQueryBuilder("mallStatus", "7"));
        //构建query查询条件
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        if (isChineseRegex.matcher(searchKey).find()) {
            query.should(new WildcardQueryBuilder("commodityName", "*" + searchKey + "*").boost(10))
                    .should(new MatchPhraseQueryBuilder("commodityName.chinese", searchKey).boost(5));

        } else {
            searchKey = searchKey.toLowerCase();
            query.should(new WildcardQueryBuilder("commodityName.pinyin", "*" + searchKey + "*").boost(15))
                    .should(new PrefixQueryBuilder("keyWord.pinyin", searchKey).boost(10));
        }

        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withIndices(commodityIndex)
                .withTypes(commodityIndexType)
                .withFilter(filter)
                .withQuery(query)
                .withPageable(PageRequest.of(pageNum, pageSize))
                .withFields("commodityName")
                .build();
        AggregatedPage<SearchSuggestVO> result = elasticsearchTemplate.queryForPage(searchQuery, SearchSuggestVO.class);
        PageData<SearchSuggestVO> data = new PageData<>();
        data.setTotalCount((int)result.getTotalElements());
        data.setPageNum(pageNum);
        data.setPageSize(pageSize);
        data.setDataList(result.getContent());
        return JsonResult.success(data);
    }
    /**
     * @Description: 基于spring-data-elasticsearch的ElasticsearchCrudRepository接口的API
     * @param
     * @return
     * @throws Exception
     * @author majun
     * @date 2019/3/18 11:49
     * @version 1.0
     */
    private JsonResult<PageData<SearchSuggestVO>> searchSuggestV3(String searchKey, int pageNum, int pageSize) {
        Page<SearchSuggestVO> result = repository.getByQueryStr(searchKey,PageRequest.of(pageNum,pageSize));
        PageData<SearchSuggestVO> data = new PageData<>();
        data.setTotalCount((int)result.getTotalElements());
        data.setPageNum(pageNum);
        data.setPageSize(pageSize);
        data.setDataList(result.getContent());
        return JsonResult.success(data);
    }
@Repository
//默认入口类@EnableElasticsearchRepositories开启的,通过@query指定查询条件,通//过SearchSuggestVO注解@Document(indexName = "mallt_XXX_index",type = //"mallt_XXX")指定要查询的索引,ElasticsearchCrudRepository继承//spring-data-common的PagingAndSortingRepository接口,该接口的抽象实现类也要//依赖ElasticsearchTemplate 

public interface CommoditySearchRepository extends ElasticsearchCrudRepository<SearchSuggestVO, String> {
@Query(" {\n" +
        "        \"bool\": {\n" +
        "            \"should\": [\n" +
        "                {\n" +
        "                    \"wildcard\": {\n" +
        "                        \"commodityName.pinyin\": {\n" +
        "                            \"wildcard\": \"*?0*\",\n" +
        "                            \"boost\": 15\n" +
        "                        }\n" +
        "                    }\n" +
        "                },\n" +
        "                {\n" +
        "                    \"prefix\": {\n" +
        "                        \"keyWord.pinyin\": {\n" +
        "                            \"value\": \"?0\",\n" +
        "                            \"boost\": 10\n" +
        "                        }\n" +
        "                    }\n" +
        "                }\n" +
        "            ],\n" +
        "            \"adjust_pure_negative\": true,\n" +
        "            \"boost\": 1\n" +
        "        }\n" +
        "    },\n" +
        "    \"post_filter\": {\n" +
        "        \"bool\": {\n" +
        "            \"must\": [\n" +
        "                {\n" +
        "                    \"term\": {\n" +
        "                        \"mallStatus\": {\n" +
        "                            \"value\": \"7\",\n" +
        "                            \"boost\": 1\n" +
        "                        }\n" +
        "                    }\n" +
        "                }\n" +
        "            ],\n" +
        "            \"adjust_pure_negative\": true,\n" +
        "            \"boost\": 1\n" +
        "        }\n" +
        "    },\n" +
        "    \"_source\": {\n" +
        "        \"includes\": [\n" +
        "            \"commodityName\"\n" +
        "        ],\n" +
        "        \"excludes\": []\n" +
        "    }")
Page<SearchSuggestVO> getByQueryStr(String keyword,Pageable pageable);
  • Redis部分:redisTemplate与jedisCluster区别

redisTempalte不是基于jedisCluster装饰实现,它对操作Redis的所有API进行了归类,

对应通用的API,redisTempalte直接调用,对应其它数据类型及集群操作通过redisTempalte.posForXXX来获取其操作对象。

 

默认RedisTemplate的key和value都是使用jdk方式序列化,如下user对象必须实现Serializable 接口,如果需要系列化为json,可以自己配置RedisTemplate并设置key、value的序列化方式,如序列化为json就不用实现序列化接口。redisTemplate.setValueSerializer(RedisSerializer.json())

示例:
redisTemplate.opsForValue().set("aaaa",new User("123",11),  Duration.ofSeconds(10));
        User aaaa = (User)redisTemplate.opsForValue().get("aaaa");

  • MongoDB部分:mongoClient原始API很少使用,spring-data-mongodb的api类似spring-data-elasticsearch,也有mongoTemplate 和继承一个MongoRepository接口(该接口依然是继承了spring-data-common的PagingAndSortingRepository,依赖mongoTemplate)。后者 仍然是不够灵活,不适合操作较复杂条件的查询。推荐mongoTemplate,链式编程构建查询条件,传入clazz自动映射结果集。
  • Query query = new Query()
                    .addCriteria(Criteria.where("username").regex("^[a-zA-Z0-9_]{4,15}$"))
                    .addCriteria(Criteria.where("age").lt(18))
                    .skip(10)
                    .limit(1);
            List<User> user = mongoTemplate.find(query, User.class, "user");

     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值