ElasticSearch Suggest Completion 智能补全技术 整合SpringBoot+Vue实现

效果演示视频和教学讲解视频地址:演示地址

1.首先在Kibana中创建索引和类型。

PUT /campus_market
{
  "mappings": {
    "product" : {
      "properties" : {
        "name" : {
          "type": "text",
          "analyzer": "ik_max_word",
          "fields": {
            "suggest" : {
              "type" : "completion",
              "analyzer": "ik_max_word"
            }
          }
        },
        "info": {
          "type": "text",
          "analyzer": "ik_max_word"
        }
      }
    }
  }
}

2.然后在Kibana中导入文档数据,或者在SpringBoot中项目导出也是可以。本人是采取后者的做法,创建一个定时任务,定时从MySQL中取出数据然后更新ES中的数据。

 @Scheduled(cron = "*/20 * * * * ?") //20s执行一次
//    @Scheduled(cron = "0 */10 * * * ?") //10分钟执行一次
    private void configureESTasks() {
        logger.info("开始更新ES中数据....");
        ResponseDTO<List<ProductDTO>> productDTOList = productService.getProductList(new ProductDTO());
        List<Product> productList = CopyUtil.copyList(productDTOList.getData(), Product.class);
        List<Product> allProductList = productMapper.selectByExample(new ProductExample());
        //先清空ElasticSearch中的数据
        for(Product product : allProductList) {
            productRepository.delete(product);
        }
        //从数据库中查询出数据添加到ES中
        for(Product product : productList){
            productRepository.save(product);
        }
        logger.info("更新ES中数据完成....");
    }

写定时任务之前,别忘了先给对应实体类创建Repository接口并且要在配置文件中进行相应配置
Repository接口

public interface ProductRepository extends ElasticsearchRepository<Product,String> {

}

config配置文件配置

@Configuration
public class ESRestClientConfig extends AbstractElasticsearchConfiguration {

    @Override
    @Bean
    public RestHighLevelClient elasticsearchClient() {
        final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo("127.0.0.1:9200")
                .build();
        return RestClients.create(clientConfiguration).rest();
    }
}

3.接下来就是正戏了,写业务逻辑层代码!!!进行SuggestBuilder创建,然后获取查询出来的结果(代码中的keyword就是查询匹配的结果内容),返回给前端。


    @Qualifier("elasticsearchClient")
    @Autowired
    private RestHighLevelClient restHighLevelClient;

  /**
     * 智能匹配搜索
     * @param productDTO
     * @return
     */
    @Override
    public ResponseDTO<List<String>> suggestCompletionProduct(ProductDTO productDTO) {
        List<String> resultList = new ArrayList<>();
        CompletionSuggestionBuilder suggestion = SuggestBuilders
                .completionSuggestion("name.suggest").prefix(productDTO.getName()).skipDuplicates(true);
        SuggestBuilder suggestBuilder = new SuggestBuilder();
        suggestBuilder.addSuggestion("product", suggestion);


        SearchRequest searchRequest = new SearchRequest();
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.suggest(suggestBuilder);
        searchRequest.indices("campus_market").types("product").source(searchSourceBuilder);
        try {
            SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            Suggest suggest = response.getSuggest();
            //SearchResponse response = elasticsearchRestTemplate.suggest(suggestBuilder, Product.class);
            int maxSuggestNum = 0; // 最多5个
            if (suggest != null) {
                List<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>> entries
                        = suggest.getSuggestion("product").getEntries();
                for (Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option> entry : entries) {
                    for (Suggest.Suggestion.Entry.Option option : entry.getOptions()) {
                        String keyword = option.getText().string();
                        if (maxSuggestNum < 5) {
                            resultList.add(keyword);
                            maxSuggestNum++;
                        } else {
                            break;
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseDTO.errorByMsg(CodeMsg.SYSTEM_ERROR);
        }

        return ResponseDTO.success(resultList);
    }

4.前端Vue要对用户输入的内容进行监听,然后调用接口获取数据。

 <div class="search-input">
	<el-input v-model="searchName" placeholder="搜一搜好货" @input="changeInput" clearable>
	     <el-select v-model="searchCategoryId" slot="prepend">
	         <el-option label="全部类目" value="0"></el-option>
	         <el-option v-for="(item, index) in categoryList" :key="index" :label="item.name" :value="item.id"></el-option>
	     </el-select>
	 </el-input>
	 <div class="suggest-content">
	     <div class="suggest-content-item" @click="toProductDetail(item.id)" v-for="(item, index) in suggestList" :key="index">
	         {{item.name}}
	     </div>
	 </div>
</div>
 changeInput(e) {
     let _this = this;
     // 函数节流,防止数据频繁更新,每300毫秒才搜索一次
     if (!this.timer) {
         this.timer = setTimeout(function(){
             _this.getSuggestList(e);
             _this.timer = null;
         },300)
     }
 },
 getSuggestList(e) {
      let _this = this;
      this.$ajax.post(process.env.VUE_APP_SERVER + "/product/suggest", {name: e}).then((response)=>{
          let resp = response.data;
          let resultList = [];
          if(resp.code === 0){
              let data = resp.data;
              _this.productList.forEach(item => {
                 data.forEach(name => {
                     if(item.name === name) {
                         let val = {
                             id: item.id,
                             name: item.name
                         };
                         resultList.push(val);
                     }
                 })
              });
          }
          _this.suggestList = resultList;
      });
  }
 .suggest-content {
     position: absolute;
     background: #fff;
     width: 480px;
     margin-left: 110px;
     border: 1px solid #444444;
     z-index: 1;
     height: auto;
     max-height: 300px;
     overflow-y: auto;
     display: block;
 }

 .suggest-content-item {
     width: 98%;
     margin: 5px 5px;
     cursor: pointer;
 }

  .search-input .el-select {
      width: 110px;
  }

  .search-input {
      width: 590px;
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这里是杨杨吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值