elasticsearch整合Springboot实现搜索功能

目录

1 通过es的mapping定义数据结构

Es的默认数据类型

定义如下es的mapping结构

2 导入Jest依赖

3  es的mysql数据导入

配置application.properties

定义es数据结构对应的java类

将mysql数据插入es中

测试查询

4  es的复杂查询

查询以下条件的手机

es中的并集处理

查询api

es用jest执行查询语句

查询dsl的封装工具类

5 搜索服务的完成+排序+高亮

定义查询参数的pojo

Controller

service

结果


1 通过es的mapping定义数据结构

Es的默认数据类型

定义如下es的mapping结构

PUT gmall0105
{
 "mappings": {
   "PmsSkuInfo":{
     "properties": {
       "id":{
        "type": "double"
      },
      "skuName":{
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "skuDesc":{
        "type": "text"
        , "analyzer": "ik_smart"
      },
      "catalog3Id":{
        "type": "keyword"
      },
      "price":{
        "type": "double"
      },
      "skuDefaultImg":{
        "type": "keyword",
        "index": false
      },
      "hotScore":{
        "type": "double"
      },
      "productId":{
        "type": "keyword"
      },
      "skuAttrValueList":{
        "properties": {
          "attrId":{
            "type":"keyword"
          },
          "valueId":{
            "type":"keyword"
          }
        }
      }
     } 
   }
 } 
}

注意:es里面的string类型(比如keyword和text在后面排序的时候可能存在问题,就不会变成数字比较,而是字符串比较。所以id定义为了double类型)

2 导入Jest依赖

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

<!-- https://mvnrepository.com/artifact/io.searchbox/jest -->
<dependency>
   <groupId>io.searchbox</groupId>
   <artifactId>jest</artifactId>
   <version>5.3.3</version>
</dependency>


<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
<dependency>
   <groupId>net.java.dev.jna</groupId>
   <artifactId>jna</artifactId>
   <version>4.5.1</version>
</dependency>

 

其中jestjna请将版本号,部分纳入gmall-parent中管理。spring-boot-starter-data-elasticsearch不用管理版本号,其版本跟随springboot1.5.10大版本号。

3  es用的mysql数据导入

配置application.properties

spring.elasticsearch.jest.uris=http://192.168.67.163:9200

定义es数据结构对应的java类

public class PmsSkuSearchInfo implements Serializable {
    @Id
    private long id;
    private String skuName;
    private String skuDesc;
    private String catalog3Id;
    private BigDecimal price;
    private String skuDefaultImg;
    private double hotScore;
    private String productId;
    private List<PmsSkuAttrValue> skuAttrValueList;
}

将mysql数据插入es中

@RunWith(SpringRunner.class)
@SpringBootTest
public class GmallSearchServiceApplicationTests {

    @Reference
    private SkuService skuService; //查询mysql

    @Autowired
    private JestClient jestClient;

    @Test
    public void put() throws IOException {
        // 查询mysql数据
        List<PmsSkuInfo> pmsSkuInfoList = new ArrayList<>();

        pmsSkuInfoList = skuService.getAllSku();

        // 转化为es的数据结构
        List<PmsSkuSearchInfo> pmsSearchSkuInfos = new ArrayList<>();

        for (PmsSkuInfo pmsSkuInfo : pmsSkuInfoList) {
            PmsSkuSearchInfo pmsSearchSkuInfo = new PmsSkuSearchInfo();

            BeanUtils.copyProperties(pmsSkuInfo,pmsSearchSkuInfo);

            pmsSearchSkuInfo.setId(Long.parseLong(pmsSkuInfo.getId()));

            pmsSearchSkuInfos.add(pmsSearchSkuInfo);

        }

        // 导入es
        for (PmsSkuSearchInfo pmsSearchSkuInfo : pmsSearchSkuInfos) {
            Index put = new Index.Builder(pmsSearchSkuInfo).index("gmall0105").type("PmsSkuInfo").id(pmsSearchSkuInfo.getId()+"").build();
            jestClient.execute(put);
        }
    }
}

注意:

测试查询

4  es的复杂查询

查询以下条件的手机

1 查询所有名字中带华为

2 查询所有4寸以下,16G内存

Query{

Bool:{// 先过滤,后查询

   Filter:{term,term}

   must:{match}

}

}

es中的并集处理

在一个过滤条件中加入并集

查询api

Search search = new Search.Builder("dsl的json语句").addIndex("索引名").addType("表名").build();

es用jest执行查询语句

​​ @Test
    public void get() throws IOException {
       // Search search = new Search.Builder("dsl的json语句").addIndex("索引名").addType("表名").build();
        // 用api执行复杂查询
        List<PmsSkuSearchInfo> pmsSearchSkuInfos = new ArrayList<>();

        Search search = new Search.Builder("{\n" +
                "  \"query\": {\n" +
                "    \"bool\": {\n" +
                "      \"filter\": [\n" +
                "        {\n" +
                "          \"term\": {\n" +
                "          \"skuAttrValueList.valueId\": \"39\"\n" +
                "          }\n" +
                "        },\n" +
                "        {\n" +
                "          \"term\": {\n" +
                "          \"skuAttrValueList.valueId\": \"45\"\n" +
                "          }\n" +
                "        }\n" +
                "        ],\n" +
                "        \"must\": [\n" +
                "          {\n" +
                "            \"match\": {\n" +
                "              \"skuName\": \"小米\"\n" +
                "            }\n" +
                "          }\n" +
                "        ]\n" +
                "      }\n" +
                "    }\n" +
                "  }").addIndex("gmall0105").addType("PmsSkuInfo").build();

        SearchResult execute = jestClient.execute(search);

        List<SearchResult.Hit<PmsSkuSearchInfo, Void>> hits = execute.getHits(PmsSkuSearchInfo.class);

        for (SearchResult.Hit<PmsSkuSearchInfo, Void> hit : hits) {
            PmsSkuSearchInfo source = hit.source;

            pmsSearchSkuInfos.add(source);
        }
        System.out.println(pmsSearchSkuInfos.size());
    }

查询dsl的封装工具类

@Test
    public void get() throws IOException {

        // jest的dsl工具
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // bool
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        // filter
        TermQueryBuilder termQueryBuilder = new TermQueryBuilder("skuAttrValueList.valueId","43");
        boolQueryBuilder.filter(termQueryBuilder);
        // must
        MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("skuName","小米");
        boolQueryBuilder.must(matchQueryBuilder);
        // query
        searchSourceBuilder.query(boolQueryBuilder);
        // from
        searchSourceBuilder.from(0);
        // size
        searchSourceBuilder.size(20);
        // highlight
        searchSourceBuilder.highlight(null);

        String dslStr = searchSourceBuilder.toString();

        System.err.println(dslStr);

       // Search search = new Search.Builder("dsl的json语句").addIndex("索引名").addType("表名").build();
        // 用api执行复杂查询
        List<PmsSkuSearchInfo> pmsSearchSkuInfos = new ArrayList<>();

        Search search = new Search.Builder("").addIndex("gmall0105").addType("PmsSkuInfo").build();

        SearchResult execute = jestClient.execute(search);

        List<SearchResult.Hit<PmsSkuSearchInfo, Void>> hits = execute.getHits(PmsSkuSearchInfo.class);

        for (SearchResult.Hit<PmsSkuSearchInfo, Void> hit : hits) {
            PmsSkuSearchInfo source = hit.source;

            pmsSearchSkuInfos.add(source);
        }
        System.out.println(pmsSearchSkuInfos.size());
    }

5 搜索服务的完成+排序+高亮

(前端代码省略)

定义查询参数的pojo

public class PmsSearchParam implements Serializable {
    private String catalog3Id;
    private String keyword;
    private List<PmsSkuAttrValue> skuAttrValueList;
}

Controller

@Controller
@CrossOrigin
public class SearchController {
    @Reference
    private SearchService searchService;

    @RequestMapping("/list.html")
    public String list(PmsSearchParam pmsSearchParam, ModelMap map){ //三级分类id,关键字
        //调用搜索服务,返回搜索结果
        List<PmsSkuSearchInfo> pmsSkuSearchInfos = searchService.list(pmsSearchParam);
        map.put("skuLsInfoList",pmsSkuSearchInfos);
        return "list";
    }
}

service

@Service
public class SearchServiceImpl implements SearchService {

    @Autowired
    private JestClient jestClient;

    @Override
    public List<PmsSkuSearchInfo> list(PmsSearchParam pmsSearchParam) {

        String dslStr =  getSearchDsl(pmsSearchParam);

        System.err.println(dslStr);

        // 用api执行复杂查询
        List<PmsSkuSearchInfo> pmsSearchSkuInfos = new ArrayList<>();

        Search search = new Search.Builder(dslStr).addIndex("gmall0105").addType("PmsSkuInfo").build();

        SearchResult execute = null;
        try {
            execute = jestClient.execute(search);
        } catch (IOException e) {
            e.printStackTrace();
        }

        List<SearchResult.Hit<PmsSkuSearchInfo, Void>> hits = execute.getHits(PmsSkuSearchInfo.class);

        for (SearchResult.Hit<PmsSkuSearchInfo, Void> hit : hits) {
            PmsSkuSearchInfo source = hit.source;

            //获取高亮内容
            Map<String, List<String>> highlight = hit.highlight;
            if(highlight!=null){
                String skuName = highlight.get("skuName").get(0);
                source.setSkuName(skuName);
            }
            pmsSearchSkuInfos.add(source);
        }

        System.err.println(pmsSearchSkuInfos.size());

        return pmsSearchSkuInfos;
    }

    private String getSearchDsl(PmsSearchParam pmsSearchParam) {
        List<PmsSkuAttrValue> skuAttrValueList = pmsSearchParam.getSkuAttrValueList();
        String keyword = pmsSearchParam.getKeyword();
        String catalog3Id = pmsSearchParam.getCatalog3Id();

        // jest的dsl工具
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // bool
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        // filter
        if (StringUtils.isNotBlank(catalog3Id)){
            TermQueryBuilder termQueryBuilder = new TermQueryBuilder("catalog3Id",catalog3Id);
            boolQueryBuilder.filter(termQueryBuilder);
        }
        if (skuAttrValueList != null) {
            for (PmsSkuAttrValue pmsSkuAttrValue : skuAttrValueList) {
                TermQueryBuilder termQueryBuilder = new TermQueryBuilder("skuAttrValueList.valueId", pmsSkuAttrValue.getValueId());
                boolQueryBuilder.filter(termQueryBuilder);
            }
        }
        // must
        if (StringUtils.isNotBlank(keyword)) {
            MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("skuName", keyword);
            boolQueryBuilder.must(matchQueryBuilder);
        }
        // query
        searchSourceBuilder.query(boolQueryBuilder);
        // from
        searchSourceBuilder.from(0);
        // size
        searchSourceBuilder.size(20);
        // highlight:高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<span style='color:red;'>");//前缀
        highlightBuilder.field("skuName");
        highlightBuilder.postTags("</span>");//后缀
        searchSourceBuilder.highlight(highlightBuilder);
        //sort
        searchSourceBuilder.sort("id", SortOrder.DESC);

        String dslStr = searchSourceBuilder.toString();

        return dslStr;
    }
}

 

 

 

 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Elasticsearch是一个开源的分布式全文搜索和分析引擎,而Spring Boot是Java开发的一种快速开发框架。将两者整合可以提供一个强大的搜索和分析功能的应用程序。 使用Spring Boot整合Elasticsearch的过程如下: 1. 首先,在pom.xml文件中添加Elasticsearch和Spring Boot相关的依赖项。例如,添加spring-boot-starter-data-elasticsearch依赖来使用Spring Data Elasticsearch模块。 2. 在应用程序的配置文件中,配置Elasticsearch的连接参数,如主机地址、端口号等。可以使用Spring Boot的配置注解来简化配置过程。 3. 创建一个实体类,使用注解定义其映射到Elasticsearch索引的方式。可以使用@Document注解设置索引名称、类型等属性,使用@Field注解设置字段的映射方式。 4. 创建一个Elasticsearch的Repository接口,继承自Spring Data Elasticsearch提供的ElasticsearchRepository接口。可以使用该接口提供的方法来进行索引的增删改查操作。 5. 在需要使用Elasticsearch的业务逻辑中,注入创建的Repository接口实例,通过调用其方法来实现对索引的操作。例如,可以使用save方法保存实体对象到索引中,使用deleteById方法删除索引中的记录。 通过以上步骤,就可以实现Elasticsearch和Spring Boot的整合。使用Spring Boot可以极大地简化了配置和开发的过程,而Elasticsearch提供了强大的全文搜索和分析功能,可以为应用程序提供高效的搜索和查询性能。整合后的应用程序可以方便地使用Elasticsearch进行数据索引和搜索操作。 ### 回答2: Elasticsearch是一个开源的搜索引擎,可以用于处理大量数据的搜索、分析和存储。Spring Boot是一个用于快速构建应用程序的框架,可以简化开发过程并提供各种强大功能。 将Elasticsearch与Spring Boot整合可以实现在应用程序中使用Elasticsearch进行数据的索引、搜索和分析。下面是一个简单的步骤来实现这个整合: 1. 添加依赖:在Spring Boot项目的pom.xml文件中,添加Elasticsearch相关的依赖。例如,可以使用spring-boot-starter-data-elasticsearch依赖来集成Elasticsearch。 2. 配置连接:在Spring Boot的配置文件中,配置Elasticsearch连接的相关信息,如主机地址、端口号、用户名和密码等。 3. 创建实体类:根据需要,创建要在Elasticsearch中索引的实体类。实体类一般使用注解来标识其在Elasticsearch中的索引和字段的映射关系。 4. 创建Repository:使用Spring Data Elasticsearch提供的@Repository注解来创建Elasticsearch的Repository接口。这个接口可以继承ElasticsearchRepository,并提供一些自定义的查询方法。 5. 编写业务逻辑:在Service层编写业务逻辑,调用自定义的Repository接口方法来对Elasticsearch进行操作。 6. 启动应用程序:使用Spring Boot的注解@SpringBootApplication来启动应用程序,其中会自动加载Elasticsearch的配置和相关的依赖。 通过以上步骤,我们就成功地将Elasticsearch整合到了Spring Boot应用程序中。可以通过访问RESTful接口来对Elasticsearch进行索引、搜索和分析等操作。此外,Spring Boot还提供了自动化配置和简化开发的特性,让整合过程更加方便快捷。 总结起来,通过整合Elasticsearch和Spring Boot,我们可以利用Elasticsearch强大的搜索和存储功能来处理大量的数据,并结合Spring Boot框架的优势快速构建应用程序。 ### 回答3: Elasticsearch是一个基于Lucene的开源搜索和分析引擎,而Spring Boot是一个使用Java快速构建生产级别的应用程序的框架。将Elasticsearch与Spring Boot整合可以提供强大的全文搜索和数据分析功能。 首先,我们需要在Spring Boot项目中添加Elasticsearch的依赖。可以通过在pom.xml文件中添加以下代码来实现: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> ``` 然后,我们需要创建一个Elasticsearch的配置类,用于配置Elasticsearch的连接信息。可以通过创建一个类,并添加`@Configuration`和`@EnableElasticsearchRepositories`注解来实现: ```java @Configuration @EnableElasticsearchRepositories(basePackages = "com.example.elasticsearch.repository") public class ElasticsearchConfig { @Value("${elasticsearch.host}") private String host; @Value("${elasticsearch.port}") private int port; @Bean public Client client() throws UnknownHostException { Settings settings = Settings.builder() .put("cluster.name", "elasticsearch").build(); TransportClient client = new PreBuiltTransportClient(settings); client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(host), port)); return client; } @Bean public ElasticsearchTemplate elasticsearchTemplate() throws UnknownHostException { return new ElasticsearchTemplate(client()); } } ``` 在上述代码中,我们通过从配置文件中读取主机和端口信息创建了一个Elasticsearch的客户端连接,并创建了一个用于Elasticsearch操作的ElasticsearchTemplate对象。 接下来,我们可以创建一个持久化层的接口,用于定义Elasticsearch的操作方法。可以通过创建一个接口,并添加`@Repository`注解来实现。例如: ```java @Repository public interface UserRepository extends ElasticsearchRepository<User, String> { List<User> findByName(String name); } ``` 在上述代码中,我们定义了一个UserRepository接口,继承了ElasticsearchRepository接口,并定义了一个按照名字查询用户的方法。 最后,我们可以在业务层或者控制层使用Elasticsearch相关的方法来进行搜索和分析操作。例如,我们可以在服务类中调用UserRepository的方法来实现用户的搜索: ```java @Service public class UserService { @Autowired private UserRepository userRepository; public List<User> searchUser(String name) { return userRepository.findByName(name); } } ``` 通过以上步骤,我们就可以在Spring Boot项目中实现Elasticsearch整合和使用了。通过配置Elasticsearch连接信息、定义操作方法和调用相关方法,可以方便地实现全文搜索和数据分析的功能
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值