ES整合SpringBoot并实现京东搜索

目录

1.springboot整合ES

1.1 添加依赖

1.2 创建一个配置,获取ES工具类对象。

1.3 进行相关对ES操作

1.3.1 操作索引---创建索引

1.3.2 操作索引--删除索引

1.3.3 索引操作--判断索引是否存在

1.3.4 操作文档---添加文档

1.3.5 查询文档--id

1.3.6 判断文档是否存在

1.3.7 删除文档

1.3.8 修改文档

1.3.9 批量添加文档

1.3.10 复杂查询

2.实现京东搜索

2.1 前端页面展示

2.2 后端结构框架展示

2.3 后端代码

2.3.1 对应依赖

2.3.2 CommonResult

2.3.3 util层(ESconfig)

2.3.4 util层(HtmlParseUtil)

2.3.5 entity层(Product)

2.3.6 controller层(JdController)

2.3.7 service层(JdService)

2.4 IK分词

2.5 前端代码

2.5.1 App.vue

2.5.2 main.js


1.springboot整合ES

1.1 添加依赖

<properties>
        <java.version>1.8</java.version>
        <!-- 统一版本window下载好的版本 -->
        <elasticsearch.version>7.6.1</elasticsearch.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--导入elasticsearch-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
        <!--导入fastjson、-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.71</version>
        </dependency>
    </dependencies>

1.2 创建一个配置,获取ES工具类对象。

@Configuration
public class ElaticsearchConfig {
//该对象可以对ES进行相关的操作
    @Bean
    public RestHighLevelClient restHighLevelClient(){
        RestHighLevelClient client=new RestHighLevelClient(RestClient.builder(new HttpHost("127.0.0.1",9200,"http")));
        return client;
    }
}

1.3 进行相关对ES操作

        这些操作可以在测试类中编写

1.3.1 操作索引---创建索引

        类型名可以不写,这样的话默认为_doc,这样就不会显示过期提示了。此处图例只是为了举例,更方便理解代码。

     @Autowired
    private RestHighLevelClient restHighLevelClient;
     //PUT  /索引名称
    //索引的操作
    @Test
    void contextLoads() throws IOException {
        //1.创建索引
        CreateIndexRequest createIndexRequest=new CreateIndexRequest("wd_my");
        CreateIndexResponse createIndexResponse=restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        //查看创建是否成功,打印结果为true,去客户端查看全部,看是否创建
        System.out.println(createIndexResponse.isAcknowledged());
        restHighLevelClient.close();
    }

 1.3.2 操作索引--删除索引

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Test
    public void test02() throws IOException {
        //索引的删除
        DeleteIndexRequest deleteIndexRequest=new DeleteIndexRequest("wd_my");
        AcknowledgedResponse delete = restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
        boolean acknowledged = delete.isAcknowledged();
        System.out.println(acknowledged);
        restHighLevelClient.close();
    }

 1.3.3 索引操作--判断索引是否存在

     @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Test
    public void test01() throws IOException {
        //索引的获取,并判断其是否存在
        GetIndexRequest indexRequest=new GetIndexRequest("wd_my");
        boolean exists = restHighLevelClient.indices().exists(indexRequest, RequestOptions.DEFAULT);
        System.out.println(exists);

        restHighLevelClient.close();
    }

1.3.4 操作文档---添加文档

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Test
    public void test03() throws IOException {
        //文档的添加
        IndexRequest indexRequest=new IndexRequest("wd_my");
        indexRequest.id("1");
        User user=new User("肖可可",15);
        indexRequest.source(JSON.toJSONString(user), XContentType.JSON);
        IndexResponse index = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        System.out.println(index.status());
        System.out.println(index);

        restHighLevelClient.close();
    }

1.3.5 查询文档--id

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Test
    public void test04() throws IOException {
        //测试获得文档的信息
        GetRequest getRequest=new GetRequest("wd_my","1");
        GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
        //打印文档内容
        System.out.println(getResponse);
        //返回的全部内容和命令是一样的
        System.out.println(getRequest);
        restHighLevelClient.close();
    }

1.3.6  判断文档是否存在

@Autowired
    private RestHighLevelClient restHighLevelClient;
 @Test
    public void test05() throws IOException {
       //文档的获取,并判断是否存在 2返回的是false 1返回的是true
       GetRequest getRequest=new GetRequest("wd_my","2");
        boolean exists = restHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);
        System.out.println(exists);
        restHighLevelClient.close();
    }

1.3.7 删除文档

@Autowired
    private RestHighLevelClient restHighLevelClient;
 @Test
    public void test07() throws IOException {
        //删除文档
        DeleteRequest deleteRequest=new DeleteRequest("wd_my","1");
        DeleteResponse delete = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
        System.out.println(delete.status());
        restHighLevelClient.close();
    }

 1.3.8 修改文档

@Autowired
    private RestHighLevelClient restHighLevelClient;
 @Test
    public void test06() throws IOException {
        //更新文档
        UpdateRequest updateRequest=new UpdateRequest("wd_my","1");
        User user=new User("肖海洋",27);
        updateRequest.doc(JSON.toJSONString(user),XContentType.JSON);
        UpdateResponse update = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
        System.out.println(update.status());
        restHighLevelClient.close();
    }

1.3.9 批量添加文档

 //批量添加文档
    @Test
    public void testBuck() throws Exception{
        BulkRequest  bulk=new BulkRequest("wd_my");
        List<User> list=new ArrayList<>();
        list.add(new User("2","张三","北京",22));
        list.add(new User("3","李四","上海",20));
        list.add(new User("4","王五","杭州",25));
        list.add(new User("5","赵六","广州",27));
        list.add(new User("6","孙七","南京",29));

        //list.stream().forEach(item->bulk.add(new IndexRequest().id(item.getId()).source(JSON.toJSONString(item),XContentType.JSON)));
        for(User user:list){
             IndexRequest indexRequest=new IndexRequest();
             indexRequest.id(user.getId());
             indexRequest.source(JSON.toJSONString(user),XContentType.JSON);
             bulk.add(indexRequest);
        }



        BulkResponse bulkResponse = client.bulk(bulk,RequestOptions.DEFAULT);
        System.out.println(bulkResponse.hasFailures());
    }

1.3.10 复杂查询

    //搜索查询---GET /索引/_search
    // {
    //     "query":{
    //         "":{}
//          },
       //  "from":
     //    "size":
    //     "_source":["",""],
    //     "sort":{}

    // }

    //1. 搜索请求对象SearchRequest
    //2. 构建一个条件对象SearchSourceBuilder
    //3. 把条件对象放入搜索请求对象中
    //4. 执行搜索功能
 @Test
    public void testSearch() throws Exception{
        //
        SearchRequest searchRequest=new SearchRequest("wd_my");
        //创建一个条件对象
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
        TermQueryBuilder matchQuery = QueryBuilders.termQuery("name", "张");
        sourceBuilder.query(matchQuery);

        //分页
        sourceBuilder.from(0);
        sourceBuilder.size(1);

        //排序
//        sourceBuilder.sort("age");

        //高亮
        HighlightBuilder highlightBuilder=new HighlightBuilder();
        highlightBuilder.field("name");
        highlightBuilder.preTags("<font color='red'>");
        highlightBuilder.postTags("</font>");
        sourceBuilder.highlighter(highlightBuilder);

        searchRequest.source(sourceBuilder);


        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        System.out.println("总条数:"+searchResponse.getHits().getTotalHits().value);
        SearchHit[] hits = searchResponse.getHits().getHits();

        Arrays.stream(hits).forEach(item-> System.out.println(item.getSourceAsString()));
        Arrays.stream(hits).forEach(item-> System.out.println(item.getHighlightFields()));
    }

2.实现京东搜索

2.1 前端页面展示

 2.2 后端结构框架展示

2.3 后端代码

2.3.1 对应依赖

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--爬虫专用-->
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.11.3</version>
        </dependency>
        <!--json依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.75</version>
        </dependency>
    </dependencies>

2.3.2 CommonResult

@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult {
    private Integer code;
    private String msg;
    private Object data;
}

2.3.3 util层(ESconfig)

@Configuration
public class ESConfig {

    @Bean
    public RestHighLevelClient restHighLevelClient(){
        RestHighLevelClient restHighLevelClient=new RestHighLevelClient(RestClient.builder(
                new HttpHost("localhost",9200,"http")
        ));
        return restHighLevelClient;
    }
}

2.3.4 util层(HtmlParseUtil)

public class HtmlParseUtil {
   public static List<Product> parseJd(String keyword) throws Exception {
   // public static void main(String[] args) throws Exception{
        String path="https://search.jd.com/Search?keyword="+keyword;
        //Document整个网页对象
       Connection con = Jsoup.connect(path).userAgent(
               "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36")
               .timeout(30000); // 设置连接超时时间
        Document document = con.get();
        //System.out.println(document);
        //查询所有的商品信息
        Element j_goodsList = document.getElementById("J_goodsList");
        //获取某一块的商品信息
        Elements li = j_goodsList.getElementsByTag("li");

         List<Product> list=new ArrayList<>();
        for (Element element : li) {
            String price = element.getElementsByClass("p-price").eq(0).text();
            //System.out.println(price);
            String pname = element.getElementsByClass("p-name").eq(0).text();
            //System.out.println(pname);
            String img = element.getElementsByTag("img").eq(0).attr("data-lazy-img");
            //System.out.println(img);
            String title = element.getElementsByClass("p-shopnum").eq(0).text();
            //System.out.println(title);

           list.add(new Product(pname,price,img,title));
        }
       return list;

    }
}

2.3.5 entity层(Product)

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product {
    private String pname;
    private String price;
    private String imgUrl;
    private String title;
}

2.3.6 controller层(JdController)

@RestController
@CrossOrigin//解决跨域问题
@RequestMapping("/jd")
public class JdController {

    @Autowired
    private JdService jdService;

    @GetMapping("/export/{keyword}")
    public CommonResult export(@PathVariable String keyword) throws Exception{
        return jdService.export(keyword);
    }

    @GetMapping("/search/{keyword}/{pageNum}/{pageSize}/{sortType}")
    public CommonResult search(@PathVariable String keyword,@PathVariable Integer pageNum,@PathVariable Integer pageSize,@PathVariable(required = false) String sortType) throws Exception{
        System.out.println(sortType);
        return jdService.search(keyword,pageNum,pageSize,sortType);
    }


}

2.3.7 service层(JdService)

@Service
public class JdService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    public CommonResult export(String keyword) throws Exception {

        List<Product> list = HtmlParseUtil.parseJd(keyword);
        BulkRequest bulkRequest=new BulkRequest("jd-index");

        for (Product product : list) {
            IndexRequest indexRequest=new IndexRequest();
            indexRequest.source(JSON.toJSONString(product), XContentType.JSON);
            bulkRequest.add(indexRequest);
        }

        BulkResponse bulkResponse=restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        if(bulkResponse.hasFailures()){
            return new CommonResult(5000,"添加文档失败",null);
        }else{
            return new CommonResult(2000,"添加文档成功",null);
        }
    }

    public CommonResult search(String keyword,Integer pageNum,Integer pageSize,String name) throws IOException {
        List<Map<String,Object>> list=new ArrayList();
        SearchRequest searchRequest=new SearchRequest("jd-index");
        //放置内容
        SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder();
        MatchQueryBuilder matchQueryBuilder= QueryBuilders.matchQuery("pname",keyword);
        searchSourceBuilder.query(matchQueryBuilder);
        //排序
        if(name!=null){
            searchSourceBuilder.sort(name, SortOrder.ASC);
        }
        //分页
        searchSourceBuilder.from(pageNum);
        searchSourceBuilder.size(pageSize);
        //高亮
        HighlightBuilder highlightBuilder=new HighlightBuilder();
        highlightBuilder.field("pname");
        highlightBuilder.preTags("<font color='red'>");
        highlightBuilder.postTags("</font>");

        searchSourceBuilder.highlighter(highlightBuilder);

        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse=restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);

        SearchHit[] hits = searchResponse.getHits().getHits();
        //获取total总数
        Long total = searchResponse.getHits().getTotalHits().value;
        for (SearchHit hit : hits) {
            Map<String,Object> map=hit.getSourceAsMap();
            //获取高亮字段
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField pname = highlightFields.get("pname");
            //获取对应的文本内容
            Text[] fragments = pname.getFragments();
            StringBuilder stringBuilder=new StringBuilder();
            for (Text fragment : fragments) {
                stringBuilder.append(fragment);
            }
            map.put("pname",stringBuilder);
            list.add(map);
        }
        HashMap<String,Object> map = new HashMap<>();
        map.put("total",total);
        map.put("data",list);
        return new CommonResult(2000,"查询成功",map);
    }
}

2.4 IK分词

IK分词器是ES的一个插件,主要用于把一段中文或者英文的划分成一个个的关键字,我们在搜索时候会把自己的信息进行分词,会把数据库中或者索引库中的数据进行分词,然后进行一个匹配操作,默认的中文分词器是将每个字看成一个词,比如"我爱技术"会被分为"我","爱","技","术",这显然不符合要求,所以我们需要安装中文分词器IK来解决这个问题;

IK提供了两个分词算法:ik_smart和ik_max_word

ik_smart为最少切分,添加了歧义识别功能,推荐;

ik_max_word为最细切分,能切的都会被切掉;

GET /_analyze
{
  "text":"你爱学习,天天向上",
  "analyzer":"ik_max_word"
}

 GET /_analyze
{
  "text":"你爱学习,天天向上",
  "analyzer":"ik_smart"
}

添加自定义词语:

在许多情况下会有一些专业数据,例如:

  "于敏为祖国奉献一生", ik_smart分词后的结果是:

而于敏是人名,被拆分开来了,需要将其作为一个词语添加到词典中;

在IK目录下有config文件夹,用于存储词典;

创建一个文件:   mydict.dic , 在里面添加"于敏"

然后要是想将多个词语放置其中,只需要使用entry键隔开:

注意:配置完成后,要重启elasticsearch搜索引擎。

除此之外:要删除对应的索引,重新创建索引。

2.5 前端代码

2.5.1 App.vue

<template>
  <div class="page">
    <div id="app" class=" mallist tmall- page-not-market ">
      <!-- 头部搜索 -->
      <div id="header" class=" header-list-app">
        <div class="headerLayout">
          <div class="headerCon ">
            <!-- Logo-->
            <div class="header-extra">
              <!--搜索-->
              <div id="mallSearch" class="mall-search">
                <form name="searchTop" class="mallSearch-form clearfix">
                  <fieldset>
                    <legend>天猫搜索</legend>
                    <div class="mallSearch-input clearfix">
                      <div class="s-combobox" id="s-combobox-685">
                        <div class="s-combobox-input-wrap">
                          <input v-model="keyword"  type="text" autocomplete="off" id="mq"
                                 class="s-combobox-input"  aria-haspopup="true">
                        </div>
                      </div>
                      <button type="submit" @click.prevent="searchKey" id="searchbtn">搜索</button>
                    </div>
                  </fieldset>
                </form>
                <ul class="relKeyTop">
                  <li><a @click="search('java')">java</a></li>
                  <li><a @click="search('vue')">vue</a></li>
                  <li><a @click="search('c#')">c#</a></li>
                  <li><a @click="search('c++')">c++</a></li>
                  <li><a @click="search('javascript')">javascript</a></li>
                </ul>
              </div>
            </div>
          </div>
        </div>
      </div>
      <!-- 商品详情页面 -->
      <div id="content">
        <div class="main">
          <!-- 品牌分类 -->
          <form class="navAttrsForm">
            <div class="attrs j_NavAttrs" style="display:block">
              <div class="brandAttr j_nav_brand">
                <div class="j_Brand attr">
                  <div class="attrKey">
                    品牌
                  </div>
                  <div class="attrValues">
                    <ul class="av-collapse row-2">
                      <li><a href="#"> vue </a></li>
                      <li><a href="#"> Java </a></li>
                    </ul>
                  </div>
                </div>
              </div>
            </div>
          </form>
          <!-- 排序规则 -->
          <div class="filter clearfix">
            <a class="fSort fSort-cur">综合<i class="f-ico-arrow-d"></i></a>
            <a class="fSort">人气<i class="f-ico-arrow-d"></i></a>
            <a class="fSort">新品<i class="f-ico-arrow-d"></i></a>
            <a class="fSort">销量<i class="f-ico-arrow-d"></i></a>
            <a class="fSort" @click="sort('price')">价格<i class="f-ico-triangle-mt"></i><i class="f-ico-triangle-mb"></i></a>
          </div>
          <!-- 商品详情 -->
          <div class="view grid-nosku" >
            <div class="product" v-for="item in results">
              <div class="product-iWrap">
                <!--商品封面-->
                <div class="productImg-wrap">
                  <a class="productImg">
                    <img :src="item.imgUrl">
                  </a>
                </div>
                <!--价格-->
                <p class="productPrice">
                  <em>{{item.price}}</em>
                </p>
                <!--标题-->
                <p class="productTitle">
                  <a v-html="item.pname">  </a>
                </p>
                <!-- 店铺名 -->
                <div class="productShop">
                  <a v-html="item.title">  </a>
                </div>
                <!-- 成交信息 -->
                <p class="productStatus">
                  <span>月成交<em>999笔</em></span>
                  <span>评价 <a>3</a></span>
                </p>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!--分页-->
      <el-pagination
              @size-change="handleSizeChange"
              @current-change="handleCurrentChange"
              :current-page="pageNum"
              :page-sizes="pageSizes"
              :page-size="pageSize"
              layout="total, sizes, prev, pager, next, jumper"
              :total="tal">
      </el-pagination>
    </div>
  </div>
</template>

<script>
  export default {
    name: "jd",
    data(){
      return {
        keyword: '', // 搜索的关键字
        results:[], // 后端返回的结果
        sortType:'',
        //分页
        pageNum:1,
        pageSize:5,
        pageSizes:[],
        tal:0,
      }
    },
    methods:{
      search(keyword){
        this.keyword = keyword;
        this.searchKey();
      },
      sort(sortType){
        this.sortType = sortType;
        this.searchKey();
      },
      searchKey(){
        var keyword = this.keyword;
        this.$http.get('/jd/search/'+keyword+"/"+this.pageNum+"/"+this.pageSize+"/price").then(response=>{
          this.results=response.data.data.data;
          console.log(this.results);
          let sizes = [];
          this.tal = response.data.data.total;
          let page = this.tal%5 === 0 ? this.tal/5 : this.tal/5+1;
          sizes.push(1);
          for(let i=1; i<=page; i++){
            sizes.push(5*i);
          }
          this.pageSizes = sizes;
        })
      },
      //分页部分内容
      handleSizeChange(val) {
        this.pageSize = val;
        this.searchKey();
      },
      handleCurrentChange(val) {
        this.pageNum = val;
        this.searchKey();
      },
    }

  }
</script>

对应样式

<style>
  /*** uncss> filename: http://localhost:9090/css/global.css ***/
  body,button,fieldset,form,h1,input,legend,li,p,ul{
    margin:0;padding:0
  }
  body,button,input{
    font:12px/1.5 tahoma,arial,"\5b8b\4f53";
    -ms-overflow-style:scrollbar
  }
  button,h1,input{
    font-size:100%
  }
  em{
    font-style:normal
  }
  ul{
    list-style:none
  }
  a{
    text-decoration:none;
    cursor: pointer;
  }
  a:hover{
    text-decoration:underline
  }
  legend{
    color:#000
  }
  fieldset,img{
    border:0
  }
  #content,#header{
    margin-left:auto;margin-right:auto
  }
  html{
    zoom:expression(function(ele){ ele.style.zoom = "1"; document.execCommand("BackgroundImageCache", false, true); }(this))}@font-face{font-family:mui-global-iconfont;src:url(//at.alicdn.com/t/font_1401963178_8135476.eot);src:url(//at.alicdn.com/t/font_1401963178_8135476.eot?#iefix) format('embedded-opentype'),url(//at.alicdn.com/t/font_1401963178_8135476.woff) format('woff'),url(//at.alicdn.com/t/font_1401963178_8135476.ttf) format('truetype'),url(//at.alicdn.com/t/font_1401963178_8135476.svg#iconfont) format('svg')}#mallPage{width:auto;min-width:990px;background-color:transparent}#content{width:990px;margin:auto}#mallLogo{float:left;z-index:9;padding-top:28px;width:280px;height:64px;line-height:64px;position:relative}.page-not-market #mallLogo{width:400px}.clearfix:after,.clearfix:before,.headerCon:after,.headerCon:before{display:table;content:"";overflow:hidden}#mallSearch legend{display:none}.clearfix:after,.headerCon:after{clear:both}.clearfix,.headerCon{zoom:1}#mallPage #header{margin-top:-30px;width:auto;margin-bottom:0;min-width:990px;background:#fff}#header{height:122px;margin-top:-26px!important;background:#fff;min-width:990px;width:auto!important;position:relative;z-index:1000}#mallSearch #mq,#mallSearch fieldset,.mallSearch-input{position:relative}.headerLayout{width:990px;padding-top:26px;margin:0 auto}.header-extra{overflow:hidden}#mallSearch{float:right;padding-top:25px;width:390px;overflow:hidden}.mallSearch-form{border:solid #FF0036;border-width:3px 0 3px 3px}.mallSearch-input{background:#fff;height:30px}#mallSearch #mq{color:#000;margin:0;z-index:2;width:289px;height:20px;line-height:20px;padding:5px 3px 5px 5px;outline:0;border:none;font-weight:900;background:url(data:image/gif;base64,R0lGODlhAQADAJEAAObm5t3d3ff39wAAACH5BAAAAAAALAAAAAABAAMAAAICDFQAOw==) repeat-x;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}#mallSearch button{position:absolute;right:0;top:0;width:90px;border:0;font-size:16px;letter-spacing:4px;cursor:pointer;color:#fff;background-color:#FF0036;height:30px;overflow:hidden;font-family:'\5FAE\8F6F\96C5\9ED1',arial,"\5b8b\4f53"}#mallSearch .s-combobox{height:30px}#mallSearch .s-combobox .s-combobox-input:focus{outline:0}button::-moz-focus-inner{border:0;padding:0;margin:0}.page-not-market #mallSearch{width:540px!important}.page-not-market #mq{width:439px!important}
  /*** uncss> filename: http://localhost:9090/css/test.css ***/#mallSearch{float:none}.page-not-market #mallLogo{width:280px}.header-list-app #mallSearch{width:448px!important}.header-list-app #mq{width:347px!important}@media (min-width:1210px){#header .headerCon,#header .headerLayout,.main{width:1190px!important}.header-list-app #mallSearch{width:597px!important}.header-list-app #mq{width:496px!important}}@media (min-width:600px) and (max-width:800px) and (orientation:portrait){.pg .page{min-width:inherit!important}.pg #mallPage,.pg #mallPage #header{min-width:740px!important}.pg #header .headerCon,.pg #header .headerLayout,.pg .main{width:740px!important}.pg #mallPage #mallLogo{width:260px}.pg #header{min-width:inherit}.pg #mallSearch .mallSearch-input{padding-right:95px}.pg #mallSearch .s-combobox{width:100%!important}.pg #mallPage .header-list-app #mallSearch{width:auto!important}.pg #mallPage .header-list-app #mallSearch #mq{width:100%!important;padding:5px 0 5px 5px}}i{font-style:normal}.main,.page{position:relative}.page{overflow:hidden}@font-face{font-family:tm-list-font;src:url(//at.alicdn.com/t/font_1442456441_338337.eot);src:url(//at.alicdn.com/t/font_1442456441_338337.eot?#iefix) format('embedded-opentype'),url(//at.alicdn.com/t/font_1442456441_338337.woff) format('woff'),url(//at.alicdn.com/t/font_1442456441_338337.ttf) format('truetype'),url(//at.alicdn.com/t/font_1442456441_338337.svg#iconfont) format('svg')}::selection{background:rgba(0,0,0,.1)}*{-webkit-tap-highlight-color:rgba(0,0,0,.3)}b{font-weight:400}.page{background:#fff;min-width:990px}#content{margin:0!important;width:100%!important}.main{margin:auto;width:990px}.main img{-ms-interpolation-mode:bicubic}.fSort i{background:url(//img.alicdn.com/tfs/TB1XClLeAY2gK0jSZFgXXc5OFXa-165-206.png) 9999px 9999px no-repeat}#mallSearch .s-combobox{width:auto}::-ms-clear,::-ms-reveal{display:none}.attrKey{white-space:nowrap;text-overflow:ellipsis}.attrs{border-top:1px solid #E6E2E1}.attrs a{outline:0}.attr{background-color:#F7F5F5;border-color:#E6E2E1 #E6E2E1 #D1CCC7;border-style:solid solid dotted;border-width:0 1px 1px}.attr ul:after,.attr:after{display:block;clear:both;height:0;content:' '}.attrKey{float:left;padding:7px 0 0;width:10%;color:#B0A59F;text-indent:13px}.attrKey{display:block;height:16px;line-height:16px;overflow:hidden}.attrValues{position:relative;float:left;background-color:#FFF;width:90%;padding:4px 0 0;overflow:hidden}.attrValues ul{position:relative;margin-right:105px;margin-left:25px}.attrValues ul.av-collapse{overflow:hidden}.attrValues li{float:left;height:22px;line-height:22px}.attrValues li a{position:relative;color:#806F66;display:inline-block;padding:1px 20px 1px 4px;line-height:20px;height:20px;white-space:nowrap}.attrValues li a:hover{color:#ff0036;text-decoration:none}.brandAttr .attr{border:2px solid #D1CCC7;margin-top:-1px}.brandAttr .attrKey{padding-top:9px}.brandAttr .attrValues{padding-top:6px}.brandAttr .av-collapse{overflow:hidden;max-height:60px}.brandAttr li{margin:0 8px 8px 0}.brandAttr li a{text-overflow:ellipsis;overflow:hidden}.navAttrsForm{position:relative}.relKeyTop{padding:4px 0 0;margin-left:-13px;height:16px;overflow:hidden;width:100%}.relKeyTop li{display:inline-block;border-left:1px solid #ccc;line-height:1.1;padding:0 12px}.relKeyTop li a{color:#999}.relKeyTop li a:hover{color:#ff0036;text-decoration:none}.filter i{display:inline-block;overflow:hidden}.filter{margin:10px 0;padding:5px;position:relative;z-index:10;background:#faf9f9;color:#806f66}.filter i{position:absolute}.filter a{color:#806f66;cursor:pointer}.filter a:hover{color:#ff0036;text-decoration:none}.fSort{float:left;height:22px;line-height:20px;line-height:24px\9;border:1px solid #ccc;background-color:#fff;z-index:10}.fSort{position:relative}.fSort{display:inline-block;margin-left:-1px;overflow:hidden;padding:0 15px 0 5px}.fSort:hover,a.fSort-cur{color:#ff0036;background:#F1EDEC}.fSort i{top:6px;right:5px;width:7px;height:10px;line-height:10px}.fSort .f-ico-arrow-d{background-position:-22px -23px}.fSort-cur .f-ico-arrow-d,.fSort:hover .f-ico-arrow-d{background-position:-30px -23px}i.f-ico-triangle-mb,i.f-ico-triangle-mt{border:4px solid transparent;height:0;width:0}i.f-ico-triangle-mt{border-bottom:4px solid #806F66;top:2px}i.f-ico-triangle-mb{border-top:4px solid #806F66;border-width:3px\9;right:6px\9;top:12px}:root i.f-ico-triangle-mb{border-width:4px\9;right:5px\9}i.f-ico-triangle-mb,i.f-ico-triangle-mt{border:4px solid transparent;height:0;width:0}i.f-ico-triangle-mt{border-bottom:4px solid #806F66;top:2px}i.f-ico-triangle-mb{border-top:4px solid #806F66;border-width:3px\9;right:6px\9;top:12px}:root i.f-ico-triangle-mb{border-width:4px\9;right:5px\9}.view:after{clear:both;content:' '}.productImg,.productPrice em b{vertical-align:middle}.product{position:relative;float:left;padding:0;margin:0 0 20px;line-height:1.5;overflow:visible;z-index:1}.product:hover{overflow:visible;z-index:3;background:#fff}.product-iWrap{position:absolute;background-color:#fff;margin:0;padding:4px 4px 0;font-size:0;border:1px solid #f5f5f5;border-radius:3px}.product-iWrap *{font-size:12px}.product:hover .product-iWrap{height:auto;margin:-3px;border:4px solid #ff0036;border-radius:0;-webkit-transition:border-color .2s ease-in;-moz-transition:border-color .2s ease-in;-ms-transition:border-color .2s ease-in;-o-transition:border-color .2s ease-in;transition:border-color .2s ease-in}.productPrice,.productShop,.productStatus,.productTitle{display:block;overflow:hidden;margin-bottom:3px}.view:after{display:block}.view{margin-top:10px}.view:after{height:0}.productImg-wrap{display:table;table-layout:fixed;height:210px;width:100%;padding:0;margin:0 0 5px}.productImg-wrap a,.productImg-wrap img{max-width:100%;max-height:210px}.productImg{display:table-cell;width:100%;text-align:center}.productImg img{display:block;margin:0 auto}.productPrice{font-family:arial,verdana,sans-serif!important;color:#ff0036;font-size:14px;height:30px;line-height:30px;margin:0 0 5px;letter-spacing:normal;overflow:inherit!important;white-space:nowrap}.productPrice *{height:30px}.productPrice em{float:left;font-family:arial;font-weight:400;font-size:20px;color:#ff0036}.productPrice em b{margin-right:2px;font-weight:700;font-size:14px}.productTitle{display:block;color:#666;height:14px;line-height:12px;margin-bottom:3px;word-break:break-all;font-size:0;position:relative}.productTitle *{font-size:12px;font-family:\5FAE\8F6F\96C5\9ED1;line-height:14px}.productTitle a{color:#333}.productTitle a:hover{color:#ff0036!important}.productTitle a:visited{color:#551A8B!important}.product:hover .productTitle{height:14px}.productShop{position:relative;height:22px;line-height:20px;margin-bottom:5px;color:#999;white-space:nowrap;overflow:visible}.productStatus{position:relative;height:32px;border:none;border-top:1px solid #eee;margin-bottom:0;color:#999}.productStatus span{float:left;display:inline-block;border-right:1px solid #eee;width:39%;padding:10px 1px;margin-right:6px;line-height:12px;text-align:left;white-space:nowrap}.productStatus a,.productStatus em{margin-top:-8px;font-family:arial;font-size:12px;font-weight:700}.productStatus em{color:#b57c5b}.productStatus a{color:#38b}.productImg-wrap{position:relative}.product-iWrap{min-height:98%;width:210px}.view{padding-left:5px;padding-right:5px}.view{width:1023px}.view .product{width:220px;margin-right:33px}@media (min-width:1210px){.view{width:1210px;padding-left:5px;padding-right:5px}.view .product{width:220px;margin-right:20px}}@media (min-width:600px) and (max-width:800px) and (orientation:portrait){.view{width:775px;padding-left:5px;padding-right:5px}.view .product{width:220px;margin-right:35px}}.product{height:372px}.grid-nosku .product{height:333px}

</style>

2.5.2 main.js

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Elasticsearch是一个开源的分布式全文搜索和分析引擎,而Spring BootJava开发的一种快速开发框架。将两者整合可以提供一个强大的搜索和分析功能的应用程序。 使用Spring Boot整合Elasticsearch的过程如下: 1. 首先,在pom.xml文件中添加ElasticsearchSpring 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方法删除索引中的记录。 通过以上步骤,就可以实现ElasticsearchSpring Boot整合。使用Spring Boot可以极大地简化了配置和开发的过程,而Elasticsearch提供了强大的全文搜索和分析功能,可以为应用程序提供高效的搜索和查询性能。整合后的应用程序可以方便地使用Elasticsearch进行数据索引和搜索操作。 ### 回答2: Elasticsearch是一个开源的搜索引擎,可以用于处理大量数据的搜索、分析和存储。Spring Boot是一个用于快速构建应用程序的框架,可以简化开发过程并提供各种强大功能。 将ElasticsearchSpring 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还提供了自动化配置和简化开发的特性,让整合过程更加方便快捷。 总结起来,通过整合ElasticsearchSpring Boot,我们可以利用Elasticsearch强大的搜索和存储功能来处理大量的数据,并结合Spring Boot框架的优势快速构建应用程序。 ### 回答3: Elasticsearch是一个基于Lucene的开源搜索和分析引擎,而Spring Boot是一个使用Java快速构建生产级别的应用程序的框架。将ElasticsearchSpring 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、付费专栏及课程。

余额充值