国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

公司的網(wǎng)站建設(shè)一般需要多少費用sem優(yōu)化怎么做

公司的網(wǎng)站建設(shè)一般需要多少費用,sem優(yōu)化怎么做,有哪些好的做網(wǎng)站公司好,滄浪蘇州網(wǎng)站建設(shè)本筆記內(nèi)容為黑馬頭條項目的app端文章搜索部分 目錄 一、今日內(nèi)容介紹 1、App端搜索-效果圖 2、今日內(nèi)容 二、搭建ElasticSearch環(huán)境 1、拉取鏡像 2、創(chuàng)建容器 3、配置中文分詞器 ik 4、使用postman測試 三、app端文章搜索 1、需求分析 2、思路分析 3、創(chuàng)建索引和…

本筆記內(nèi)容為黑馬頭條項目的app端文章搜索部分

目錄

一、今日內(nèi)容介紹

1、App端搜索-效果圖

2、今日內(nèi)容

二、搭建ElasticSearch環(huán)境

1、拉取鏡像

2、創(chuàng)建容器

3、配置中文分詞器 ik

4、使用postman測試

三、app端文章搜索

1、需求分析

2、思路分析

3、創(chuàng)建索引和映射

4、數(shù)據(jù)初始化到索引庫

5、文章搜索功能實現(xiàn)

6、文章自動審核構(gòu)建索引

四、app端搜索-搜索記錄

1、需求分析

2、數(shù)據(jù)存儲說明

3、MongoDB安裝及集成

4、保存搜索記錄

5、加載搜索記錄列表

6、刪除搜索記錄

五、app端搜索-關(guān)鍵字聯(lián)想詞

1、需求分析

2、搜索詞-數(shù)據(jù)來源

3、功能實現(xiàn)


一、今日內(nèi)容介紹


1、App端搜索-效果圖

2、今日內(nèi)容

  • 文章搜索

    • ElasticSearch環(huán)境搭建

    • 索引庫創(chuàng)建

    • 文章搜索多條件復(fù)合查詢

    • 索引數(shù)據(jù)同步

  • 搜索歷史記錄

    • Mongodb環(huán)境搭建

    • 異步保存搜索歷史

    • 查看搜索歷史列表

    • 刪除搜索歷史

  • 聯(lián)想詞查詢

    • 聯(lián)想詞的來源

    • 聯(lián)想詞功能實現(xiàn)

二、搭建ElasticSearch環(huán)境


1、拉取鏡像

docker pull elasticsearch:7.4.0

2、創(chuàng)建容器

docker run -id --name elasticsearch -d --restart=always -p 9200:9200 -p 9300:9300 -v /usr/share/elasticsearch/plugins:/usr/share/elasticsearch/plugins -e "discovery.type=single-node" elasticsearch:7.4.0

3、配置中文分詞器 ik

因為在創(chuàng)建elasticsearch容器的時候,映射了目錄,所以可以在宿主機上進(jìn)行配置ik中文分詞器

在去選擇ik分詞器的時候,需要與elasticsearch的版本好對應(yīng)上

把資料中的elasticsearch-analysis-ik-7.4.0.zip上傳到服務(wù)器上,放到對應(yīng)目錄(plugins)解壓

#切換目錄
cd /usr/share/elasticsearch/plugins
#新建目錄
mkdir analysis-ik
cd analysis-ik
#root根目錄中拷貝文件
mv elasticsearch-analysis-ik-7.4.0.zip /usr/share/elasticsearch/plugins/analysis-ik
#解壓文件
cd /usr/share/elasticsearch/plugins/analysis-ik
unzip elasticsearch-analysis-ik-7.4.0.zip

4、使用postman測試

三、app端文章搜索


1、需求分析

  • 用戶輸入關(guān)鍵可搜索文章列表

  • 關(guān)鍵詞高亮顯示

  • 文章列表展示與home展示一樣,當(dāng)用戶點擊某一篇文章,可查看文章詳情

2、思路分析

為了加快檢索的效率,在查詢的時候不會直接從數(shù)據(jù)庫中查詢文章,需要在elasticsearch中進(jìn)行高速檢索。

3、創(chuàng)建索引和映射

使用postman添加映射

put請求 : http://192.168.200.130:9200/app_info_article

{"mappings":{"properties":{"id":{"type":"long"},"publishTime":{"type":"date"},"layout":{"type":"integer"},"images":{"type":"keyword","index": false},"staticUrl":{"type":"keyword","index": false},"authorId": {"type": "long"},"authorName": {"type": "text"},"title":{"type":"text","analyzer":"ik_smart"},"content":{"type":"text","analyzer":"ik_smart"}}}
}

4、數(shù)據(jù)初始化到索引庫

1.導(dǎo)入es-init到heima-leadnews-test工程下

2.查詢所有的文章信息,批量導(dǎo)入到es索引庫中

package com.heima.es;import com.alibaba.fastjson.JSON;
import com.heima.es.mapper.ApArticleMapper;
import com.heima.es.pojo.SearchArticleVo;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.util.List;@SpringBootTest
@RunWith(SpringRunner.class)
public class ApArticleTest {@Autowiredprivate ApArticleMapper apArticleMapper;@Autowiredprivate RestHighLevelClient restHighLevelClient;/*** 注意:數(shù)據(jù)量的導(dǎo)入,如果數(shù)據(jù)量過大,需要分頁導(dǎo)入* @throws Exception*/@Testpublic void init() throws Exception {//1.查詢所有符合條件的文章數(shù)據(jù)List<SearchArticleVo> searchArticleVos = apArticleMapper.loadArticleList();//2.批量導(dǎo)入到es索引庫BulkRequest bulkRequest = new BulkRequest("app_info_article");for (SearchArticleVo searchArticleVo : searchArticleVos) {IndexRequest indexRequest = new IndexRequest().id(searchArticleVo.getId().toString()).source(JSON.toJSONString(searchArticleVo), XContentType.JSON);//批量添加數(shù)據(jù)bulkRequest.add(indexRequest);}restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);}}

3.測試

postman查詢所有的es中數(shù)據(jù) GET請求: http://192.168.200.130:9200/app_info_article/_search

5、文章搜索功能實現(xiàn)

1.搭建搜索微服務(wù)

①導(dǎo)入 heima-leadnews-search

②在heima-leadnews-service的pom中添加依賴

<!--elasticsearch-->
<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.4.0</version>
</dependency>
<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-client</artifactId><version>7.4.0</version>
</dependency>
<dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.4.0</version>
</dependency>

③nacos配置中心leadnews-search

spring:autoconfigure:exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
elasticsearch:host: 192.168.200.130port: 9200

2.搜索接口定義

package com.heima.search.controller.v1;import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.search.dtos.UserSearchDto;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.io.IOException;@RestController
@RequestMapping("/api/v1/article/search")
public class ArticleSearchController {@PostMapping("/search")public ResponseResult search(@RequestBody UserSearchDto dto) throws IOException {return null;}
}

UserSearchDto

package com.heima.model.search.dtos;import lombok.Data;import java.util.Date;@Data
public class UserSearchDto {/*** 搜索關(guān)鍵字*/String searchWords;/*** 當(dāng)前頁*/int pageNum;/*** 分頁條數(shù)*/int pageSize;/*** 最小時間*/Date minBehotTime;public int getFromIndex(){if(this.pageNum<1)return 0;if(this.pageSize<1) this.pageSize = 10;return this.pageSize * (pageNum-1);}
}

3.業(yè)務(wù)層實現(xiàn)

創(chuàng)建業(yè)務(wù)層接口:ApArticleSearchService

package com.heima.search.service;import com.heima.model.search.dtos.UserSearchDto;
import com.heima.model.common.dtos.ResponseResult;import java.io.IOException;public interface ArticleSearchService {/**ES文章分頁搜索@return*/ResponseResult search(UserSearchDto userSearchDto) throws IOException;
}

實現(xiàn)類:

package com.heima.search.service.impl;import com.alibaba.fastjson.JSON;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.search.dtos.UserSearchDto;
import com.heima.model.user.pojos.ApUser;
import com.heima.search.service.ArticleSearchService;
import com.heima.utils.thread.AppThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;@Service
@Slf4j
public class ArticleSearchServiceImpl implements ArticleSearchService {@Autowiredprivate RestHighLevelClient restHighLevelClient;/*** es文章分頁檢索** @param dto* @return*/@Overridepublic ResponseResult search(UserSearchDto dto) throws IOException {//1.檢查參數(shù)if(dto == null || StringUtils.isBlank(dto.getSearchWords())){return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}//2.設(shè)置查詢條件SearchRequest searchRequest = new SearchRequest("app_info_article");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//布爾查詢BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();//關(guān)鍵字的分詞之后查詢QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(dto.getSearchWords()).field("title").field("content").defaultOperator(Operator.OR);boolQueryBuilder.must(queryStringQueryBuilder);//查詢小于mindate的數(shù)據(jù)RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("publishTime").lt(dto.getMinBehotTime().getTime());boolQueryBuilder.filter(rangeQueryBuilder);//分頁查詢searchSourceBuilder.from(0);searchSourceBuilder.size(dto.getPageSize());//按照發(fā)布時間倒序查詢searchSourceBuilder.sort("publishTime", SortOrder.DESC);//設(shè)置高亮  titleHighlightBuilder highlightBuilder = new HighlightBuilder();highlightBuilder.field("title");highlightBuilder.preTags("<font style='color: red; font-size: inherit;'>");highlightBuilder.postTags("</font>");searchSourceBuilder.highlighter(highlightBuilder);searchSourceBuilder.query(boolQueryBuilder);searchRequest.source(searchSourceBuilder);SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//3.結(jié)果封裝返回List<Map> list = new ArrayList<>();SearchHit[] hits = searchResponse.getHits().getHits();for (SearchHit hit : hits) {String json = hit.getSourceAsString();Map map = JSON.parseObject(json, Map.class);//處理高亮if(hit.getHighlightFields() != null && hit.getHighlightFields().size() > 0){Text[] titles = hit.getHighlightFields().get("title").getFragments();String title = StringUtils.join(titles);//高亮標(biāo)題map.put("h_title",title);}else {//原始標(biāo)題map.put("h_title",map.get("title"));}list.add(map);}return ResponseResult.okResult(list);}
}

4.控制層實現(xiàn)

新建控制器ArticleSearchController

package com.heima.search.controller.v1;import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.search.dtos.UserSearchDto;
import com.heima.search.service.ArticleSearchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.io.IOException;@RestController
@RequestMapping("/api/v1/article/search")
public class ArticleSearchController {@Autowiredprivate ArticleSearchService articleSearchService;@PostMapping("/search")public ResponseResult search(@RequestBody UserSearchDto dto) throws IOException {return articleSearchService.search(dto);}
}

5.測試

需要在app的網(wǎng)關(guān)中添加搜索微服務(wù)的路由配置

#搜索微服務(wù)
- id: leadnews-searchuri: lb://leadnews-searchpredicates:- Path=/search/**filters:- StripPrefix= 1

啟動項目進(jìn)行測試,至少要啟動文章微服務(wù),用戶微服務(wù),搜索微服務(wù),app網(wǎng)關(guān)微服務(wù),app前端工程

6、文章自動審核構(gòu)建索引

1.思路分析

2.文章微服務(wù)發(fā)送消息

①把SearchArticleVo放到model工程下

package com.heima.model.search.vos;import lombok.Data;import java.util.Date;@Data
public class SearchArticleVo {// 文章idprivate Long id;// 文章標(biāo)題private String title;// 文章發(fā)布時間private Date publishTime;// 文章布局private Integer layout;// 封面private String images;// 作者idprivate Long authorId;// 作者名詞private String authorName;//靜態(tài)urlprivate String staticUrl;//文章內(nèi)容private String content;}

②文章微服務(wù)的ArticleFreemarkerService中的buildArticleToMinIO方法中收集數(shù)據(jù)并發(fā)送消息

完整代碼如下:

package com.heima.article.service.impl;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.heima.article.mapper.ApArticleContentMapper;
import com.heima.article.service.ApArticleService;
import com.heima.article.service.ArticleFreemarkerService;
import com.heima.common.constants.ArticleConstants;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.search.vos.SearchArticleVo;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;@Service
@Slf4j
@Transactional
public class ArticleFreemarkerServiceImpl implements ArticleFreemarkerService {@Autowiredprivate ApArticleContentMapper apArticleContentMapper;@Autowiredprivate Configuration configuration;@Autowiredprivate FileStorageService fileStorageService;@Autowiredprivate ApArticleService apArticleService;/*** 生成靜態(tài)文件上傳到minIO中* @param apArticle* @param content*/@Async@Overridepublic void buildArticleToMinIO(ApArticle apArticle, String content) {//已知文章的id//4.1 獲取文章內(nèi)容if(StringUtils.isNotBlank(content)){//4.2 文章內(nèi)容通過freemarker生成html文件Template template = null;StringWriter out = new StringWriter();try {template = configuration.getTemplate("article.ftl");//數(shù)據(jù)模型Map<String,Object> contentDataModel = new HashMap<>();contentDataModel.put("content", JSONArray.parseArray(content));//合成template.process(contentDataModel,out);} catch (Exception e) {e.printStackTrace();}//4.3 把html文件上傳到minio中InputStream in = new ByteArrayInputStream(out.toString().getBytes());String path = fileStorageService.uploadHtmlFile("", apArticle.getId() + ".html", in);//4.4 修改ap_article表,保存static_url字段apArticleService.update(Wrappers.<ApArticle>lambdaUpdate().eq(ApArticle::getId,apArticle.getId()).set(ApArticle::getStaticUrl,path));//發(fā)送消息,創(chuàng)建索引createArticleESIndex(apArticle,content,path);}}@Autowiredprivate KafkaTemplate<String,String> kafkaTemplate;/*** 送消息,創(chuàng)建索引* @param apArticle* @param content* @param path*/private void createArticleESIndex(ApArticle apArticle, String content, String path) {SearchArticleVo vo = new SearchArticleVo();BeanUtils.copyProperties(apArticle,vo);vo.setContent(content);vo.setStaticUrl(path);kafkaTemplate.send(ArticleConstants.ARTICLE_ES_SYNC_TOPIC, JSON.toJSONString(vo));}}

在ArticleConstants類中添加新的常量,完整代碼如下

package com.heima.common.constants;public class ArticleConstants {public static final Short LOADTYPE_LOAD_MORE = 1;public static final Short LOADTYPE_LOAD_NEW = 2;public static final String DEFAULT_TAG = "__all__";public static final String ARTICLE_ES_SYNC_TOPIC = "article.es.sync.topic";public static final Integer HOT_ARTICLE_LIKE_WEIGHT = 3;public static final Integer HOT_ARTICLE_COMMENT_WEIGHT = 5;public static final Integer HOT_ARTICLE_COLLECTION_WEIGHT = 8;public static final String HOT_ARTICLE_FIRST_PAGE = "hot_article_first_page_";
}

③文章微服務(wù)集成kafka發(fā)送消息

在文章微服務(wù)的nacos的配置中心添加如下配置

kafka:bootstrap-servers: 192.168.200.130:9092producer:retries: 10key-serializer: org.apache.kafka.common.serialization.StringSerializervalue-serializer: org.apache.kafka.common.serialization.StringSerializer

3.搜索微服務(wù)創(chuàng)建索引

①搜索微服務(wù)中添加kafka的配置,nacos配置如下

spring:kafka:bootstrap-servers: 192.168.200.130:9092consumer:group-id: ${spring.application.name}key-deserializer: org.apache.kafka.common.serialization.StringDeserializervalue-deserializer: org.apache.kafka.common.serialization.StringDeserializer

②定義監(jiān)聽接收消息,保存索引數(shù)據(jù)

package com.heima.search.listener;import com.alibaba.fastjson.JSON;
import com.heima.common.constants.ArticleConstants;
import com.heima.model.search.vos.SearchArticleVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;import java.io.IOException;@Component
@Slf4j
public class SyncArticleListener {@Autowiredprivate RestHighLevelClient restHighLevelClient;@KafkaListener(topics = ArticleConstants.ARTICLE_ES_SYNC_TOPIC)public void onMessage(String message){if(StringUtils.isNotBlank(message)){log.info("SyncArticleListener,message={}",message);SearchArticleVo searchArticleVo = JSON.parseObject(message, SearchArticleVo.class);IndexRequest indexRequest = new IndexRequest("app_info_article");indexRequest.id(searchArticleVo.getId().toString());indexRequest.source(message, XContentType.JSON);try {restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);} catch (IOException e) {e.printStackTrace();log.error("sync es error={}",e);}}}
}

四、app端搜索-搜索記錄


1、需求分析

2、數(shù)據(jù)存儲說明

用戶的搜索記錄,需要給每一個用戶都保存一份,數(shù)據(jù)量較大,要求加載速度快,通常這樣的數(shù)據(jù)存儲到mongodb更合適,不建議直接存儲到關(guān)系型數(shù)據(jù)庫中

3、MongoDB安裝及集成

1.安裝MongoDB

拉取鏡像

docker pull mongo

創(chuàng)建容器

docker run -di --name mongo-service --restart=always -p 27017:27017 -v ~/data/mongodata:/data mongo

2.導(dǎo)入資料中的mongo-demo項目到heima-leadnews-test中

其中有三項配置比較關(guān)鍵:

第一:mongo依賴

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

第二:mongo配置

server:port: 9998
spring:data:mongodb:host: 192.168.200.130port: 27017database: leadnews-history

第三:映射

package com.itheima.mongo.pojo;import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;import java.io.Serializable;
import java.util.Date;/*** <p>* 聯(lián)想詞表* </p>** @author itheima*/
@Data
@Document("ap_associate_words")
public class ApAssociateWords implements Serializable {private static final long serialVersionUID = 1L;private String id;/*** 聯(lián)想詞*/private String associateWords;/*** 創(chuàng)建時間*/private Date createdTime;}

3.核心方法

package com.itheima.mongo.test;import com.itheima.mongo.MongoApplication;
import com.itheima.mongo.pojo.ApAssociateWords;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.test.context.junit4.SpringRunner;import java.util.Date;
import java.util.List;@SpringBootTest(classes = MongoApplication.class)
@RunWith(SpringRunner.class)
public class MongoTest {@Autowiredprivate MongoTemplate mongoTemplate;//保存@Testpublic void saveTest(){/*for (int i = 0; i < 10; i++) {ApAssociateWords apAssociateWords = new ApAssociateWords();apAssociateWords.setAssociateWords("黑馬頭條");apAssociateWords.setCreatedTime(new Date());mongoTemplate.save(apAssociateWords);}*/ApAssociateWords apAssociateWords = new ApAssociateWords();apAssociateWords.setAssociateWords("黑馬直播");apAssociateWords.setCreatedTime(new Date());mongoTemplate.save(apAssociateWords);}//查詢一個@Testpublic void saveFindOne(){ApAssociateWords apAssociateWords = mongoTemplate.findById("60bd973eb0c1d430a71a7928", ApAssociateWords.class);System.out.println(apAssociateWords);}//條件查詢@Testpublic void testQuery(){Query query = Query.query(Criteria.where("associateWords").is("黑馬頭條")).with(Sort.by(Sort.Direction.DESC,"createdTime"));List<ApAssociateWords> apAssociateWordsList = mongoTemplate.find(query, ApAssociateWords.class);System.out.println(apAssociateWordsList);}@Testpublic void testDel(){mongoTemplate.remove(Query.query(Criteria.where("associateWords").is("黑馬頭條")),ApAssociateWords.class);}
}

4、保存搜索記錄

1.實現(xiàn)思路

用戶輸入關(guān)鍵字進(jìn)行搜索的異步記錄關(guān)鍵字

用戶搜索記錄對應(yīng)的集合,對應(yīng)實體類:

package com.heima.search.pojos;import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;import java.io.Serializable;
import java.util.Date;/*** <p>* APP用戶搜索信息表* </p>* @author itheima*/
@Data
@Document("ap_user_search")
public class ApUserSearch implements Serializable {private static final long serialVersionUID = 1L;/*** 主鍵*/private String id;/*** 用戶ID*/private Integer userId;/*** 搜索詞*/private String keyword;/*** 創(chuàng)建時間*/private Date createdTime;}

2.實現(xiàn)步驟

①搜索微服務(wù)集成mongodb

pom依賴

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

nacos配置

spring:data:mongodb:host: 192.168.200.130port: 27017database: leadnews-history

在當(dāng)天資料中找到對應(yīng)的實體類拷貝到搜索微服務(wù)下

package com.heima.search.pojos;import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;import java.io.Serializable;
import java.util.Date;/*** <p>* APP用戶搜索信息表* </p>* @author itheima*/
@Data
@Document("ap_user_search")
public class ApUserSearch implements Serializable {private static final long serialVersionUID = 1L;/*** 主鍵*/private String id;/*** 用戶ID*/private Integer userId;/*** 搜索詞*/private String keyword;/*** 創(chuàng)建時間*/private Date createdTime;}
package com.heima.search.pojos;import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;import java.io.Serializable;
import java.util.Date;/*** <p>* 聯(lián)想詞表* </p>** @author itheima*/
@Data
@Document("ap_associate_words")
public class ApAssociateWords implements Serializable {private static final long serialVersionUID = 1L;private String id;/*** 聯(lián)想詞*/private String associateWords;/*** 創(chuàng)建時間*/private Date createdTime;}

②創(chuàng)建ApUserSearchService新增insert方法

public interface ApUserSearchService {/*** 保存用戶搜索歷史記錄* @param keyword* @param userId*/public void insert(String keyword,Integer userId);
}

實現(xiàn)類:

@Service
@Slf4j
public class ApUserSearchServiceImpl implements ApUserSearchService {@Autowiredprivate MongoTemplate mongoTemplate;/*** 保存用戶搜索歷史記錄* @param keyword* @param userId*/@Override@Asyncpublic void insert(String keyword, Integer userId) {//1.查詢當(dāng)前用戶的搜索關(guān)鍵詞Query query = Query.query(Criteria.where("userId").is(userId).and("keyword").is(keyword));ApUserSearch apUserSearch = mongoTemplate.findOne(query, ApUserSearch.class);//2.存在 更新創(chuàng)建時間if(apUserSearch != null){apUserSearch.setCreatedTime(new Date());mongoTemplate.save(apUserSearch);return;}//3.不存在,判斷當(dāng)前歷史記錄總數(shù)量是否超過10apUserSearch = new ApUserSearch();apUserSearch.setUserId(userId);apUserSearch.setKeyword(keyword);apUserSearch.setCreatedTime(new Date());Query query1 = Query.query(Criteria.where("userId").is(userId));query1.with(Sort.by(Sort.Direction.DESC,"createdTime"));List<ApUserSearch> apUserSearchList = mongoTemplate.find(query1, ApUserSearch.class);if(apUserSearchList == null || apUserSearchList.size() < 10){mongoTemplate.save(apUserSearch);}else {ApUserSearch lastUserSearch = apUserSearchList.get(apUserSearchList.size() - 1);mongoTemplate.findAndReplace(Query.query(Criteria.where("id").is(lastUserSearch.getId())),apUserSearch);}}
}

3.參考自媒體相關(guān)微服務(wù),在搜索微服務(wù)中獲取當(dāng)前登錄的用戶

Util類

package com.heima.utils.thread;import com.heima.model.user.pojos.ApUser;
import com.heima.model.wemedia.pojos.WmUser;/*** Description: new java files header..** @author zhangzuhao* @version 1.0* @date 2023/7/18 15:56*/public class AppThreadLocalUtil {private final static ThreadLocal<ApUser> WM_USER_THREAD_LOCAL = new ThreadLocal<>();//存入線程中public static void setUser(ApUser apUser){WM_USER_THREAD_LOCAL.set(apUser);}//獲取線程數(shù)據(jù)public static ApUser getUser(){return WM_USER_THREAD_LOCAL.get();}//清理數(shù)據(jù)public static void clear(){WM_USER_THREAD_LOCAL.remove();}
}

interceptor

package com.heima.search.interceptor;import com.heima.model.user.pojos.ApUser;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.thread.AppThreadLocalUtil;
import com.heima.utils.thread.WmThreadLocalUtil;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** Description: new java files header..** @author zhangzuhao* @version 1.0* @date 2023/8/7 16:54*/public class AppTokenInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String userId = request.getHeader("userId");if (userId!=null){ApUser apUser = new ApUser();apUser.setId(Integer.valueOf(userId));AppThreadLocalUtil.setUser(apUser);}return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {AppThreadLocalUtil.clear();}
}

config

package com.heima.search.config;import com.heima.search.interceptor.AppTokenInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** Description: new java files header..** @author zhangzuhao* @version 1.0* @date 2023/7/18 16:06*/@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new AppTokenInterceptor()).addPathPatterns("/**");}
}

4.在ArticleSearchService的search方法中調(diào)用保存歷史記錄

完整代碼如下:

package com.heima.search.service.impl;import com.alibaba.fastjson.JSON;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.search.dtos.UserSearchDto;
import com.heima.model.user.pojos.ApUser;
import com.heima.search.service.ApUserSearchService;
import com.heima.search.service.ArticleSearchService;
import com.heima.utils.thread.AppThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;@Service
@Slf4j
public class ArticleSearchServiceImpl implements ArticleSearchService {@Autowiredprivate RestHighLevelClient restHighLevelClient;@Autowiredprivate ApUserSearchService apUserSearchService;/*** es文章分頁檢索** @param dto* @return*/@Overridepublic ResponseResult search(UserSearchDto dto) throws IOException {//1.檢查參數(shù)if(dto == null || StringUtils.isBlank(dto.getSearchWords())){return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}ApUser user = AppThreadLocalUtil.getUser();//異步調(diào)用 保存搜索記錄if(user != null && dto.getFromIndex() == 0){apUserSearchService.insert(dto.getSearchWords(), user.getId());}//2.設(shè)置查詢條件SearchRequest searchRequest = new SearchRequest("app_info_article");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//布爾查詢BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();//關(guān)鍵字的分詞之后查詢QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(dto.getSearchWords()).field("title").field("content").defaultOperator(Operator.OR);boolQueryBuilder.must(queryStringQueryBuilder);//查詢小于mindate的數(shù)據(jù)RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("publishTime").lt(dto.getMinBehotTime().getTime());boolQueryBuilder.filter(rangeQueryBuilder);//分頁查詢searchSourceBuilder.from(0);searchSourceBuilder.size(dto.getPageSize());//按照發(fā)布時間倒序查詢searchSourceBuilder.sort("publishTime", SortOrder.DESC);//設(shè)置高亮  titleHighlightBuilder highlightBuilder = new HighlightBuilder();highlightBuilder.field("title");highlightBuilder.preTags("<font style='color: red; font-size: inherit;'>");highlightBuilder.postTags("</font>");searchSourceBuilder.highlighter(highlightBuilder);searchSourceBuilder.query(boolQueryBuilder);searchRequest.source(searchSourceBuilder);SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//3.結(jié)果封裝返回List<Map> list = new ArrayList<>();SearchHit[] hits = searchResponse.getHits().getHits();for (SearchHit hit : hits) {String json = hit.getSourceAsString();Map map = JSON.parseObject(json, Map.class);//處理高亮if(hit.getHighlightFields() != null && hit.getHighlightFields().size() > 0){Text[] titles = hit.getHighlightFields().get("title").getFragments();String title = StringUtils.join(titles);//高亮標(biāo)題map.put("h_title",title);}else {//原始標(biāo)題map.put("h_title",map.get("title"));}list.add(map);}return ResponseResult.okResult(list);}
}

5.保存歷史記錄中開啟異步調(diào)用,添加注解@Async

6.在搜索微服務(wù)引導(dǎo)類上開啟異步調(diào)用

7.測試,搜索后查看結(jié)果

5、加載搜索記錄列表

1.思路分析

按照當(dāng)前用戶,按照時間倒序查詢

說明
接口路徑/api/v1/history/load
請求方式POST
參數(shù)
響應(yīng)結(jié)果ResponseResult

2.接口定義

/*** <p>* APP用戶搜索信息表 前端控制器* </p>** @author itheima*/
@Slf4j
@RestController
@RequestMapping("/api/v1/history")
public class ApUserSearchController{@PostMapping("/load")@Overridepublic ResponseResult findUserSearch() {return null;}}

3.mapper

已定義

4.業(yè)務(wù)層

在ApUserSearchService中新增方法

/**查詢搜索歷史@return*/
ResponseResult findUserSearch();

實現(xiàn)方法

 /*** 查詢搜索歷史** @return*/
@Override
public ResponseResult findUserSearch() {//獲取當(dāng)前用戶ApUser user = AppThreadLocalUtil.getUser();if(user == null){return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);}//根據(jù)用戶查詢數(shù)據(jù),按照時間倒序List<ApUserSearch> apUserSearches = mongoTemplate.find(Query.query(Criteria.where("userId").is(user.getId())).with(Sort.by(Sort.Direction.DESC, "createdTime")), ApUserSearch.class);return ResponseResult.okResult(apUserSearches);
}

5.控制器

/*** <p>* APP用戶搜索信息表 前端控制器* </p>* @author itheima*/
@Slf4j
@RestController
@RequestMapping("/api/v1/history")
public class ApUserSearchController{@Autowiredprivate ApUserSearchService apUserSearchService;@PostMapping("/load")public ResponseResult findUserSearch() {return apUserSearchService.findUserSearch();}}

6.測試

打開app的搜索頁面,可以查看搜索記錄列表

6、刪除搜索記錄

1.思路分析

按照搜索歷史id刪除

說明
接口路徑/api/v1/history/del
請求方式POST
參數(shù)HistorySearchDto
響應(yīng)結(jié)果ResponseResult

2.接口定義

在ApUserSearchController接口新增方法

@PostMapping("/del")
public ResponseResult delUserSearch(@RequestBody HistorySearchDto historySearchDto) {return null;
}

HistorySearchDto

@Data
public class HistorySearchDto {/*** 接收搜索歷史記錄id*/String id;
}

3.業(yè)務(wù)層

在ApUserSearchService中新增方法

 /**刪除搜索歷史@param historySearchDto@return*/
ResponseResult delUserSearch(HistorySearchDto historySearchDto);

實現(xiàn)方法

/*** 刪除歷史記錄** @param dto* @return*/
@Override
public ResponseResult delUserSearch(HistorySearchDto dto) {//1.檢查參數(shù)if(dto.getId() == null){return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}//2.判斷是否登錄ApUser user = AppThreadLocalUtil.getUser();if(user == null){return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);}//3.刪除mongoTemplate.remove(Query.query(Criteria.where("userId").is(user.getId()).and("id").is(dto.getId())),ApUserSearch.class);return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}

4.控制器

修改ApUserSearchController,補全方法

@PostMapping("/del")
public ResponseResult delUserSearch(@RequestBody HistorySearchDto historySearchDto) {return apUserSearchService.delUserSearch(historySearchDto);
}

5.測試

打開app可以刪除搜索記錄

五、app端搜索-關(guān)鍵字聯(lián)想詞


1、需求分析

對應(yīng)實體類

package com.heima.search.pojos;import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;import java.io.Serializable;
import java.util.Date;/*** <p>* 聯(lián)想詞表* </p>** @author itheima*/
@Data
@Document("ap_associate_words")
public class ApAssociateWords implements Serializable {private static final long serialVersionUID = 1L;private String id;/*** 聯(lián)想詞*/private String associateWords;/*** 創(chuàng)建時間*/private Date createdTime;}

2、搜索詞-數(shù)據(jù)來源

通常是網(wǎng)上搜索頻率比較高的一些詞,通常在企業(yè)中有兩部分來源:

第一:自己維護(hù)搜索詞

通過分析用戶搜索頻率較高的詞,按照排名作為搜索詞

第二:第三方獲取

關(guān)鍵詞規(guī)劃師(百度)、5118、愛站網(wǎng)

3、功能實現(xiàn)

1.接口定義

說明
接口路徑/api/v1/associate/search
請求方式POST
參數(shù)UserSearchDto
響應(yīng)結(jié)果ResponseResult

新建接口

package com.heima.search.controller.v1;import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.search.dtos.UserSearchDto;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api/v1/associate")
public class ApAssociateWordsController {@PostMapping("/search")public ResponseResult search(@RequestBody UserSearchDto userSearchDto) {return null;}
}

2.業(yè)務(wù)層

新建聯(lián)想詞業(yè)務(wù)層接口

package com.heima.search.service;import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.search.dtos.UserSearchDto;/*** <p>* 聯(lián)想詞表 服務(wù)類* </p>** @author itheima*/
public interface ApAssociateWordsService {/**聯(lián)想詞@param userSearchDto@return*/ResponseResult findAssociate(UserSearchDto userSearchDto);}

實現(xiàn)類

package com.heima.search.service.impl;import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.search.dtos.UserSearchDto;
import com.heima.search.pojos.ApAssociateWords;
import com.heima.search.service.ApAssociateWordsService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;import java.util.List;/*** @Description:* @Version: V1.0*/
@Service
public class ApAssociateWordsServiceImpl implements ApAssociateWordsService {@AutowiredMongoTemplate mongoTemplate;/*** 聯(lián)想詞* @param userSearchDto* @return*/@Overridepublic ResponseResult findAssociate(UserSearchDto userSearchDto) {//1 參數(shù)檢查if(userSearchDto == null || StringUtils.isBlank(userSearchDto.getSearchWords())){return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}//分頁檢查if (userSearchDto.getPageSize() > 20) {userSearchDto.setPageSize(20);}//3 執(zhí)行查詢 模糊查詢Query query = Query.query(Criteria.where("associateWords").regex(".*?\\" + userSearchDto.getSearchWords() + ".*"));query.limit(userSearchDto.getPageSize());List<ApAssociateWords> wordsList = mongoTemplate.find(query, ApAssociateWords.class);return ResponseResult.okResult(wordsList);}
}

3.控制器

新建聯(lián)想詞控制器

package com.heima.search.controller.v1;import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.search.dtos.UserSearchDto;
import com.heima.search.service.ApAssociateWordsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** <p>* 聯(lián)想詞表 前端控制器* </p>* @author itheima*/
@Slf4j
@RestController
@RequestMapping("/api/v1/associate")
public class ApAssociateWordsController{@Autowiredprivate ApAssociateWordsService apAssociateWordsService;@PostMapping("/search")public ResponseResult findAssociate(@RequestBody UserSearchDto userSearchDto) {return apAssociateWordsService.findAssociate(userSearchDto);}
}

4.測試

同樣,打開前端聯(lián)調(diào)測試效果

結(jié)束!

http://aloenet.com.cn/news/34967.html

相關(guān)文章:

  • 中英文網(wǎng)站asp怎么做seo推廣軟件費用
  • 找人做網(wǎng)站應(yīng)該注意什么福州seo兼職
  • 打開鏈接的網(wǎng)站網(wǎng)絡(luò)營銷計劃的七個步驟
  • 自制網(wǎng)站的動態(tài)圖怎么做創(chuàng)意廣告
  • 廣州中小企業(yè)網(wǎng)站建設(shè)免費發(fā)帖推廣的平臺
  • 深圳外文網(wǎng)站制作喬拓云智能建站官網(wǎng)
  • 福州企業(yè)網(wǎng)站推廣網(wǎng)絡(luò)營銷推廣方式
  • 馬鞍山制作網(wǎng)站網(wǎng)絡(luò)營銷方式有哪幾種
  • 學(xué)校網(wǎng)站制作2345網(wǎng)址導(dǎo)航大全
  • 做二手房的網(wǎng)站技巧網(wǎng)站做成app
  • 網(wǎng)站設(shè)計價格大概多少谷歌瀏覽器下載手機版
  • 做網(wǎng)站優(yōu)化給業(yè)務(wù)員提成百度資源提交
  • wordpress+admin主題武漢seo招聘信息
  • 揚中網(wǎng)站建設(shè) 優(yōu)幫云站長工具seo查詢5g5g
  • 珠海網(wǎng)站建設(shè)科速互聯(lián)百度知道網(wǎng)頁版進(jìn)入
  • 徐匯做網(wǎng)站無錫百度推廣公司哪家好
  • 青島做外貿(mào)網(wǎng)站建設(shè)網(wǎng)絡(luò)營銷服務(wù)的特點
  • 微信網(wǎng)站模板免費下載seo免費入門教程
  • wordpress foxseo 關(guān)鍵詞優(yōu)化
  • 快速免費建網(wǎng)站常用的營銷策略
  • 邢臺做網(wǎng)站優(yōu)化百度排名優(yōu)化軟件
  • 淮北做網(wǎng)站的公司百度seo優(yōu)化服務(wù)項目
  • 滎陽網(wǎng)站建設(shè)公司網(wǎng)絡(luò)關(guān)鍵詞優(yōu)化軟件
  • 便宜做網(wǎng)站seo算法優(yōu)化
  • 佛山正規(guī)網(wǎng)站建設(shè)報價優(yōu)化大師app下載安裝
  • 口碑好網(wǎng)站建設(shè)公司seo關(guān)鍵詞優(yōu)化平臺
  • 不同網(wǎng)站對商家做o2o的政策阿里seo排名優(yōu)化軟件
  • 湖南教育平臺網(wǎng)站建設(shè)流量寶
  • 梧州專業(yè)網(wǎng)站推廣官方百度平臺
  • 做外貿(mào)的網(wǎng)站主要有哪些內(nèi)容網(wǎng)站分析培訓(xùn)班