用SpringBoot和ElasticSearch实现网盘搜索引擎,附源码,详细教学

这篇具有很好参考价值的文章主要介绍了用SpringBoot和ElasticSearch实现网盘搜索引擎,附源码,详细教学。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最终效果如下

可以扫描小程序码体验,切换到搜索Tabbar。
网盘搜索源码,elasticsearch,搜索引擎,spring boot,微信小程序,java

小程序端界面实现

网盘搜索源码,elasticsearch,搜索引擎,spring boot,微信小程序,java

网盘搜索源码,elasticsearch,搜索引擎,spring boot,微信小程序,java
网盘搜索源码,elasticsearch,搜索引擎,spring boot,微信小程序,java

网页端实现界面

网盘搜索源码,elasticsearch,搜索引擎,spring boot,微信小程序,java
网盘搜索源码,elasticsearch,搜索引擎,spring boot,微信小程序,java

后端核心源码

对外提供的api

/**
     * 搜索网盘资源
     *
     * @param condition 条件
     * @return {@link Result< NetDiskSearchDTO >} 网盘资源列表
     */
    @ApiOperation(value = "搜索网盘资源")
    @GetMapping("/netdisks/search")
    public Result<?> listNetDisksBySearch(ConditionVO condition) {
        PageInfo pageInfo = netDiskService.listNetDisksBySearch(condition);
        return Result.ok(pageInfo);
    }

接口声明

 /**
     * 搜索网盘资源
     *
     * @param condition 条件
     * @return 网盘资源列表
     */
    PageInfo listNetDisksBySearch(ConditionVO condition);

接口实现

 @Override
    public PageInfo listNetDisksBySearch(ConditionVO condition) {
        return searchStrategyContext.executeNetDiskSearchStrategy(condition);
    }

执行搜索策略。

提供2种搜索策略,分别是MySQL和ElasticSearch搜索策略。在配置文件进行配置搜索策略。文章来源地址https://www.toymoban.com/news/detail-718419.html

package top.liuleinet.blog.strategy.context;

import com.github.pagehelper.PageInfo;
import top.liuleinet.blog.dto.NetDiskSearchDTO;
import top.liuleinet.blog.strategy.SearchStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import top.liuleinet.blog.vo.ConditionVO;

import java.util.List;
import java.util.Map;

import static top.liuleinet.blog.enums.SearchModeEnum.getStrategy;

/**
 * 搜索策略上下文
 *
 * @author Liu'Lei
 * @date 2021/07/27
 */
@Service
public class SearchStrategyContext {
    /**
     * 搜索模式
     */
    @Value("${search.mode}")
    private String searchMode;

    @Autowired
    private Map<String, SearchStrategy> searchStrategyMap;

    /**
     * 执行网盘资源搜索策略
     *
     * @param condition 关键字
     * @return {@link List<NetDiskSearchDTO>} 搜索网盘资源
     */
    public PageInfo executeNetDiskSearchStrategy(ConditionVO condition) {
        return searchStrategyMap.get(getStrategy(searchMode)).searchNetDisk(condition);
    }

}

搜索类型枚举

package top.liuleinet.blog.enums;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * 搜索类型枚举
 *
 * @author Liu'Lei
 * @date 2021/07/27
 */
@Getter
@AllArgsConstructor
public enum SearchModeEnum {
    /**
     * mysql
     */
    MYSQL("mysql", "mySqlSearchStrategyImpl"),
    /**
     * elasticsearch
     */
    ELASTICSEARCH("elasticsearch", "esSearchStrategyImpl");

    /**
     * 模式
     */
    private final String mode;

    /**
     * 策略
     */
    private final String strategy;

    /**
     * 获取策略
     *
     * @param mode 模式
     * @return {@link String} 搜索策略
     */
    public static String getStrategy(String mode) {
        for (SearchModeEnum value : SearchModeEnum.values()) {
            if (value.getMode().equals(mode)) {
                return value.getStrategy();
            }
        }
        return null;
    }

}

配置文件中的搜索策略相关配置

# 搜索模式 可选 elasticsearch或mysql
search:
  mode: elasticsearch

es搜索策略实现

package top.liuleinet.blog.strategy.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import top.liuleinet.blog.dto.NetDiskSearchDTO;
import top.liuleinet.blog.strategy.SearchStrategy;
import lombok.extern.log4j.Log4j2;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import top.liuleinet.blog.vo.ConditionVO;

import java.util.List;
import java.util.stream.Collectors;

import static top.liuleinet.blog.constant.CommonConst.*;
import static top.liuleinet.blog.enums.NetDiskStatusEnum.OPEN;
/**
 * es搜索策略实现
 *
 * @author Liu'Lei
 * @date 2021/07/27
 */
@Log4j2
@Service("esSearchStrategyImpl")
public class EsSearchStrategyImpl implements SearchStrategy {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;
    
    
    @Override
    public PageInfo searchNetDisk(ConditionVO condition) {
        if (StringUtils.isBlank(condition.getKeywords())) {
            return new PageInfo();
        }
        return searchNetdisk(buildNetdiskQuery(condition.getKeywords()), condition);
    }

    /**
     * 搜索网盘资源构造
     *
     * @param keywords 关键字
     * @return es条件构造器
     */
    private NativeSearchQueryBuilder buildNetdiskQuery(String keywords) {
        // 条件构造器
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        // 根据关键词搜索网盘资源标题
        boolQueryBuilder.must(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("netdiskTitle", keywords)))
                .must(QueryBuilders.termQuery("isDelete", FALSE))
                .must(QueryBuilders.termQuery("isVip",FALSE))
                .must(QueryBuilders.termQuery("status", OPEN.getStatus()));
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
        return nativeSearchQueryBuilder;
    }

    /**
     * 网盘资源搜索结果高亮
     *
     * @param nativeSearchQueryBuilder es条件构造器
     * @return 搜索结果
     */
    private PageInfo searchNetdisk(NativeSearchQueryBuilder nativeSearchQueryBuilder, ConditionVO condition) {
        // 添加网盘资源标题高亮
        HighlightBuilder.Field titleField = new HighlightBuilder.Field("netdiskTitle");
        titleField.preTags(PRE_TAG);
        titleField.postTags(POST_TAG);
        nativeSearchQueryBuilder.withHighlightFields(titleField);
        // 搜索
        try {
            SearchHits<NetDiskSearchDTO> search = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), NetDiskSearchDTO.class);
            List<NetDiskSearchDTO> netDiskSearchDTOS = search.getSearchHits().stream().map(hit -> {
                NetDiskSearchDTO netDisk = hit.getContent();
                // 获取标题高亮数据
                List<String> titleHighLightList = hit.getHighlightFields().get("netdiskTitle");
                if (CollectionUtils.isNotEmpty(titleHighLightList)) {
                    // 替换标题数据
                    netDisk.setNetdiskTitle(titleHighLightList.get(0));
                }
                return netDisk;
            }).collect(Collectors.toList());
            Page page = new Page(condition.getCurrent().intValue(), condition.getSize().intValue());
            page.setTotal(netDiskSearchDTOS.size());
            int startIndex = (condition.getCurrent().intValue() - 1) * condition.getSize().intValue();
            int endIndex = Math.min(startIndex + condition.getSize().intValue(),netDiskSearchDTOS.size());
            page.addAll(netDiskSearchDTOS.subList(startIndex,endIndex));
            PageInfo pageInfo = new PageInfo<>(page);
            return pageInfo;
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return new PageInfo();
    }

}


ConditionVO类如下

package top.liuleinet.blog.vo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;


/**
 * 查询条件
 *
 * @author Liu'Lei
 * @date 2021/07/29
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "查询条件")
public class ConditionVO {

    /**
     * 页码
     */
    @ApiModelProperty(name = "current", value = "页码", dataType = "Long")
    private Long current;

    /**
     * 条数
     */
    @ApiModelProperty(name = "size", value = "条数", dataType = "Long")
    private Long size;

    /**
     * 搜索内容
     */
    @ApiModelProperty(name = "keywords", value = "搜索内容", dataType = "String")
    private String keywords;


    /**
     * 网盘分类
     */
    @ApiModelProperty(name = "category", value = "分类", dataType = "String")
    private String category;

    /**
     * 类型
     */
    @ApiModelProperty(name = "type", value = "类型", dataType = "Integer")
    private Integer type;

    /**
     * 状态
     */
    @ApiModelProperty(name = "status", value = "状态", dataType = "Integer")
    private Integer status;

    /**
     * 是否删除
     */
    @ApiModelProperty(name = "isDelete", value = "是否删除", dataType = "Integer")
    private Integer isDelete;

    /**
     * 是否vip网盘资源
     */
    @ApiModelProperty(name = "isVip", value = "是否vip网盘资源", dataType = "Integer")
    private Integer isVip;
}

小程序端JavaScript代码逻辑

import {
	searchNetdisk
} from '../../services/api'


const app = getApp();

// 在页面中定义插屏广告
let interstitialAd = null;
Page({
	data: {
		StatusBar: app.globalData.StatusBar,
		CustomBar: app.globalData.CustomBar,
		noContentImage: '/images/default/no-data.png',
		historyKeyword: [],
		preRecommendKeyword: [
			'PPT模板', '动漫', 'Java', '狮子王', '万里归途', '阿甘正传', '星际穿越', '满江红', '流浪地球2', '长津湖'
		],
		recommendKeyword: [],
		recommendKeywordView: true,
		title: '资源搜索',
		keywords: '',
		current: 1,
		size: 10,
		loading: false,
		isSearch: false,
		searchResult: {},
		content: [],
		windowHeight: app.globalData.windowHeight
	},

	async onLoad() {
		var that = this;
		var historyKeyword = wx.getStorageSync('netdiskHistory');

		if (historyKeyword) {
			that.setData({
				historyKeyword: historyKeyword
			})
		}
		var preRecommendKeyword = that.data.preRecommendKeyword;
		var recommendKeyword = preRecommendKeyword.slice(0, 5);
		that.setData({
			recommendKeyword: recommendKeyword
		})

		// 在页面onLoad回调事件中创建插屏广告实例
		if (wx.createInterstitialAd) {
			interstitialAd = wx.createInterstitialAd({
				adUnitId: 'adunit-9b1d1f3ffba7cf75'
			})
			interstitialAd.onLoad(() => {})
			interstitialAd.onError((err) => {})
			interstitialAd.onClose(() => {})
		}


	},

	async clickSearch(e) {
		var that = this;
		that.setData({
			keywords: e.currentTarget.dataset.keyword
		})
		await that.search();
	},

	/**
	 * 搜索
	 * @param {*} event
	 */
	async search() {
		var that = this;
		var keywords = that.data.keywords;
		var historyKeywordArray = that.data.historyKeyword;
		if (historyKeywordArray.indexOf(keywords) === -1) {
			historyKeywordArray.unshift(keywords);
			if (historyKeywordArray.length > 10) {
				historyKeywordArray.pop();
			}
			wx.setStorageSync('netdiskHistory', historyKeywordArray);
		}
		that.setData({
			historyKeyword: historyKeywordArray
		})
		await that.getNetdiskList(true, keywords);
		that.setData({
			isSearch: true,
		})
	},

	/**
	 * 搜索输入事件
	 * @param {s} event
	 */
	searchInput(event) {
		var that = this;
		//console.log(event)
		that.setData({
			keywords: event.detail.value,
			isSearch: true
		})
	},
	/**
	 * 清空历史搜索关键字
	 */
	clearHistoryKeyword() {
		var that = this;
		wx.removeStorageSync('netdiskHistory');
		that.setData({
			historyKeyword: []
		})
	},
	changeRecommend() {
		var that = this;
		var arr = that.data.preRecommendKeyword;
		var randomCommendArr = that.getRandomArrayElements(arr, 5);
		that.setData({
			recommendKeyword: randomCommendArr
		})
	},
	changeRecommendView() {
		var that = this;
		that.setData({
			recommendKeywordView: !that.data.recommendKeywordView
		})
	},



	/**
	 * 顶部刷新
	 */
	// async onPullDownRefresh() {
	//   // 显示顶部刷新图标
	//   wx.showNavigationBarLoading()
	//   const that = this
	//   const content = await this.getNetdiskList(true, this.data.keywords)
	//   that.setData({
	//     content: content
	//   })
	//   setTimeout(function () {
	//     // 隐藏导航栏加载框
	//     wx.hideNavigationBarLoading()
	//     // 停止当前页面下拉刷新。
	//     wx.stopPullDownRefresh()
	//   }, 1500)
	// },


	/**
	 * 向下滑动拉去下一页
	 */
	async onReachBottom() {
		var that = this;
		var current = ++that.data.current;
		that.setData({
			current: current,
			content: []
		})
		// 在适合的场景显示插屏广告
		if (interstitialAd && current == 2) {
			interstitialAd.show().catch((err) => {
				console.error(err);
			})
		}
		//console.log(current)
		if (current > that.data.searchResult.pages) {
			wx.showToast({
				title: '已经是最后一页',
			})
		}
		var keyword = that.data.keywords;
		await that.getNetdiskList(false,keyword);
	},

	/**
	 * 向上一页
	 */
	async toPreviousPage() {
		var that = this;
		var current = --that.data.current;
		that.setData({
			current: current
		})
		var keyword = that.data.keywords;
		await that.getNetdiskList(false, keyword);
	},
	/**
	 * 获取网盘资源列表
	 */
	async getNetdiskList(init, keywords) {
		var that = this;
		if (keywords.length == 0) {
			wx.showToast({
				title: '关键词不能为空!',
			})
			return;
		}
		
			if (init) {
				that.initParams();
			}
			var current = that.data.current;
			var size = that.data.size;
			var param = {
				keywords: keywords,
				current: current,
				size: size
			}
			var result = await searchNetdisk(param);
			var resData = result.data;
			var resDataList = resData.list;
			that.setData({
				searchResult: resData,
				content: resDataList
			})
			return;
	},
	/**
	 * 初始化页数和内容
	 */
	initParams() {
		var that = this;
		that.setData({
			searchResult: {},
			content: [],
			current: 1
		})
	},
	toHome() {
		var that = this;
		that.setData({
			isSearch:false
		})
	},
	// backPre() {
	//   this.setData({
	//     isSearch: !this.data.isSearch
	//   })
	// },

	/**
	 * 数组中随机取几个元素
	 * @param {*} arr 来源数组
	 * @param {*} count 取数量
	 */
	getRandomArrayElements(arr, count) {
		var shuffled = arr.slice(0),
			i = arr.length,
			min = i - count,
			temp, index;
		while (i-- > min) {
			index = Math.floor((i + 1) * Math.random());
			temp = shuffled[index];
			shuffled[index] = shuffled[i];
			shuffled[i] = temp;
		}
		return shuffled.slice(min);
	},

	/**
	 * 分享
	 * @param {*} res
	 */
	onShareAppMessage: function (res) {
		var that = this;
		return {
			title: that.data.keywords + '!,点击打开',
			path: '/pages/netdisk/index'
		}
	},
	onShareTimeline: function (res) {
		var that = this;
		return {
			title: that.data.keywords + '!,点击打开'
		}
	}
})

到了这里,关于用SpringBoot和ElasticSearch实现网盘搜索引擎,附源码,详细教学的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 搜索引擎ElasticSearch分布式搜索和分析引擎学习,SpringBoot整合ES个人心得

    Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。Elasticsearch用于云计算中,能够达到实时搜索,稳定,可靠,

    2024年02月04日
    浏览(57)
  • 15 个百度网盘搜索引擎

    1、云铺子 - 百度网盘搜索引擎 地址:http://www.yunpz.net/ 查看方式:直接打开 推荐指数:★★★★★ 备注:聚合类,体验好, 推荐! 2、橘子盘搜-好用的影视资源搜索引擎 地址:https://www.nmme.cc/ 查看方式:直接打开 推荐指数:★★★★★ 备注:专攻影视搜索,度盘、迅雷、

    2023年04月08日
    浏览(72)
  • 分享个自己开发的夸克网盘资源搜索引擎

    https://www.cuppaso.com/ 框架使用了 spring boot 全家桶 2.7.1版本 mybatis plus 最新版本3.5.1 es搜索引擎 版本的话是 elasticsearch-7.17.4-windows-x86_64

    2024年02月12日
    浏览(37)
  • 推荐几款实用的网盘资源搜索引擎

    网盘搜索引擎是一个用于搜索互联网上各种网盘资源的工具。它能够帮助用户快速找到所需的文件,并提供下载链接。它可以搜索多个网盘站点,包括360安全网盘、360云盘、腾讯微云、阿里云盘等等。用户只需输入想要搜索的,网盘搜索引擎就会自动搜索所有相关的网

    2024年02月13日
    浏览(37)
  • 6个最好用的网盘资源搜索引擎,大汇总!

    分享 6 个 专业网盘搜索引擎 ,支持百度网盘、阿里云盘、蓝奏云盘、夸克网盘、天翼云盘、迅雷云盘等。 全都是免费网站,简单好用,必须点赞收藏! # 1. 无为盘搜 - 网盘搜索引擎界新星! 地址:https://wuweipansou.top 支持网盘:聚合搜索,阿里、百度、夸克、天翼 查看方式

    2024年02月08日
    浏览(173)
  • 【搜索引擎2】实现API方式调用ElasticSearch8接口

    1、理解ElasticSearch各名词含义 ElasticSearch对比Mysql Mysql数据库 Elastic Search Database 7.X版本前有Type,对比数据库中的表,新版取消了 Table Index Row Document Column mapping Elasticsearch是使用Java开发的,8.1版本的ES需要JDK17及以上版本;es默认带有JDK,如果安装es环境为java8,则会默认使用自带

    2024年04月17日
    浏览(30)
  • elasticsearch[五]:深入探索ES搜索引擎的自动补全与拼写纠错:如何实现高效智能的搜索体验

    前一章讲了搜索中的拼写纠错功能,里面一个很重要的概念就是莱文斯坦距离。这章会讲解搜索中提升用户体验的另一项功能 - [自动补全]。本章直接介绍 ES 中的实现方式以及真正的搜索引擎对自动补全功能的优化。 大家对上面的这个应该都不陌生,搜索引擎会根据你输入的

    2024年01月24日
    浏览(40)
  • 如何使用内网穿透工具实现Java远程连接本地Elasticsearch搜索分析引擎

    简单几步,结合Cpolar 内网穿透工具实现Java 远程连接操作本地分布式搜索和数据分析引擎Elasticsearch。 Cpolar内网穿透提供了更高的安全性和隐私保护,通过使用加密通信通道,Cpolar技术可以确保数据传输的安全性,这为用户和团队提供了更可靠的保护,使他们能够放心地处理和

    2024年02月04日
    浏览(42)
  • 分布式搜索和分析引擎Elasticsearch本地部署结合内网穿透实现远程访问

    本文主要介绍如何在Windows系统部署分布式搜索和分析引擎Elasticsearch,并结合Cpolar内网穿透工具实现公网远程连接和访问本地服务。 Elasticsearch是一个基于Lucene库的分布式搜索和分析引擎,它提供了一个分布式、多租户的全文搜索引擎,具有HTTP Web接口和无模式JSON文档,同时也

    2024年01月21日
    浏览(36)
  • 《Spring Boot 实战派》--13.集成NoSQL数据库,实现Elasticsearch和Solr搜索引擎

             关于搜索引擎 我们很难实现 Elasticseach 和 Solr两大搜索框架的效果;所以本章针对两大搜索框架,非常详细地讲解 它们的原理和具体使用方法, 首先 介绍什么是搜索引擎 、如何用 MySQL实现简单的搜索引擎,以及Elasticseach 的 概念和接口类; 然后介绍Elasticseach

    2023年04月09日
    浏览(77)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包