writer.addDocument(document);
writer.commit();
writer.close();
}

/**

  • 索引实体列表
  • @param objects 实例列表
  • @throws IOException IO 异常
    */
    public void addModelDocs(List<?> objects) throws IOException {
    if (CollectionUtils.isNotEmpty(objects)) {
    List docs = new ArrayList<>();
    objects.forEach(o -> {
    Document document = new Document();
    List fields = luceneField(o);
    fields.forEach(document::add);
    docs.add(document);
    });
    writer.addDocuments(docs);
    }
    }

/**

  • 清除所有文档
  • @throws IOException IO 异常
    */
    public void delAllDocs() throws IOException {
    writer.deleteAll();
    }

/**

  • 索引文档列表
  • @param docs 文档列表
  • @throws IOException IO 异常
    */
    public void addDocs(List docs) throws IOException {
    if (CollectionUtils.isNotEmpty(docs)) {
    long startTime = System.currentTimeMillis();
    writer.addDocuments(docs);
    writer.commit();
    log.info(“共索引{}个 Document,共耗时{} 毫秒”, docs.size(), (System.currentTimeMillis() - startTime));
    } else {
    log.warn(“索引列表为空”);
    }
    }

/**

  • 根据实体 class 对象获取字段类型,进行 lucene Field 字段映射
  • @param modelObj 实体 modelObj 对象
  • @return 字段映射列表
    */
    public List luceneField(Object modelObj) {
    Map<String, Object> classFields = ReflectionUtils.getClassFields(modelObj.getClass());
    Map<String, Object> classFieldsValues = ReflectionUtils.getClassFieldsValues(modelObj);

List fields = new ArrayList<>();
for (String key : classFields.keySet()) {
Field field;
String dataType = StringUtils.substringAfterLast(classFields.get(key).toString(), “.”);
switch (dataType) {
case “Integer”:
field = new IntPoint(key, (Integer) classFieldsValues.get(key));
break;
case “Long”:
field = new LongPoint(key, (Long) classFieldsValues.get(key));
break;
case “Float”:
field = new FloatPoint(key, (Float) classFieldsValues.get(key));
break;
case “Double”:
field = new DoublePoint(key, (Double) classFieldsValues.get(key));
break;
case “String”:
String string = (String) classFieldsValues.get(key);
if (StringUtils.isNotBlank(string)) {
if (string.length() <= 1024) {
field = new StringField(key, (String) classFieldsValues.get(key), Field.Store.YES);
} else {
field = new TextField(key, (String) classFieldsValues.get(key), Field.Store.NO);
}
} else {
field = new StringField(key, StringUtils.EMPTY, Field.Store.NO);
}
break;
default:
field = new TextField(key, JsonUtils.obj2Json(classFieldsValues.get(key)), Field.Store.YES);
break;
}
fields.add(field);
}
return fields;
}
public void close() {
if (null != writer) {
try {
writer.close();
} catch (IOException e) {
log.error(“close writer error”);
}
writer = null;
}
}

public void commit() throws IOException {
if (null != writer) {
writer.commit();
writer.close();
}
}
}

有了工具类,我们再写一个 demo 来进行数据的索引

import java.util.ArrayList;
import java.util.List;

/**

  • Function:
  • Author:@author Silence
  • Date:2020-10-17 21:08
  • Desc:

    */
    public class Demo {
    public static void main(String[] args) {
    LuceneIndexUtil luceneUtil = LuceneIndexUtil.getInstance();
    List articles = new ArrayList<>();
    try {
    //索引数据
    ArticleModel article1 = new ArticleModel();
    article1.setTitle(“J 《大厂前端面试题解析+Web核心总结学习笔记+企业项目实战源码+最新高清讲解视频》无偿开源 徽信搜索公众号【编程进阶路】 ava天下第一”);
    article1.setAuthor(“粉丝”);
    article1.setContent(“这是一篇给大家介绍 Lucene 的技术文章,必定点赞评论转发!!!”);
    ArticleModel article2 = new ArticleModel();
    article2.setTitle(“天下第一”);
    article2.setAuthor(“粉丝”);
    article2.setContent(“此处省略两千字…”);
    ArticleModel article3 = new ArticleModel();
    article3.setTitle(“Java天下第一”);
    article3.setAuthor(“粉丝”);
    article3.setContent(“Today is big day!”);
    articles.add(article1);
    articles.add(article2);
    articles.add(article3);
    luceneUtil.addModelDocs(articles);
    luceneUtil.commit();

} catch (Exception e) {
e.printStackTrace();
}
}
}

上面的 content 内容可以自行进行替换,小编这边避免凑字数的嫌疑就不贴了。

展示

运行结束过后,我们用过 Lucene 的可视化工具 luke 来查看下索引的数据内容,下载过后解压我们可以看到有.bat 和 .sh 两个脚本,根据自己的系统进行运行就好了。小编这边是 mac 用的是 sh 脚本运行,运行后打开设置的索引目录即可。

进入过后,我们可以看到下图显示的内容,选择 content 点击 show top items 可以看到右侧的索引数据,这里根据分词器的不同,索引的结果是不一样的,小编这里采用的分词器就是标准的分词器,小伙伴们可以根据自己的要求选择适合自己的分词器即可。

搜索数据

数据已经索引成功了,接下来我们就需要根据条件进行数据的搜索了,我们创建一个 LuceneSearchUtil.java 来操作数据。

import org.apache.commons.collections.MapUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.springframework.beans.factory.annotation.Value;

import java.io.IOException;
import java.nio.file.Paths;
import java.util.Map;

public class LuceneSearchUtil {

private static String INDEX_PATH = “/opt/lucene/demo”;
private static IndexSearcher searcher;

public static LuceneSearchUtil getInstance() {
return LuceneSearchUtil.SingletonHolder.searchUtil;
}

private static class SingletonHolder {
public final static LuceneSearchUtil searchUtil = new LuceneSearchUtil();
}

private LuceneSearchUtil() {
this.initSearcher();
}

private void initSearcher() {
Directory directory;
try {
directory = FSDirectory.open(Paths.get(INDEX_PATH));
DirectoryReader reader = DirectoryReader.open(directory);
searcher = new IndexSearcher(reader);
} catch (IOException e) {
e.printStackTrace();
}
}

public TopDocs searchByMap(Map<String, Object> queryMap) throws Exception {
if (null == searcher) {
this.initSearcher();
}
if (MapUtils.isNotEmpty(queryMap)) {
BooleanQuery.Builder builder = new BooleanQuery.Builder();
queryMap.forEach((key, value) -> {
if (value instanceof String) {
Query queryString = new PhraseQuery(key, (String) value);
// Query queryString = new TermQuery(new Term(key, (String) value));
builder.add(queryString, BooleanClause.Occur.MUST);
}
});
return searcher.search(builder.build(), 10);
}
return null;
}

}

在 demo.java 中增加搜索代码如下:

//查询数据
Map<String, Object> map = new HashMap<>();
map.put(“title”, “Java 天下第一”);
// map.put(“title”, “天下第一”);
// map.put(“content”, “最”);
LuceneSearchUtil searchUtil = LuceneSearchUtil.getInstance();
TopDocs topDocs = searchUtil.searchByMap(map);
System.out.println(topDocs.totalHits);

map.put(“title”, “Java 天下第一”);
// map.put(“title”, “天下第一”);
// map.put(“content”, “最”);
LuceneSearchUtil searchUtil = LuceneSearchUtil.getInstance();
TopDocs topDocs = searchUtil.searchByMap(map);
System.out.println(topDocs.totalHits);

只用了几百行代码写的百度搜索引擎,你看咋样?相关推荐

  1. 几百行代码写个Mybatis,原理搞的透透的!

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!

  2. python写百行代码可运行_56 岁潘石屹学俩月 Python ,写下百行代码

    原标题:56 岁潘石屹学俩月 Python ,写下百行代码 By 超神经 内容导读:跨界王潘石屹在近期迷上了编程,不仅高调宣布学习 Python,拜老师,还隔三差五晒出自己的「编程课作业」,和网友进行 ...

  3. Kaggle—So Easy!百行代码实现排名Top 5%的图像分类比赛

    北京 上海巡回站 | NVIDIA DLI深度学习培训 2018年1月26/1月12日 NVIDIA 深度学习学院 带你快速进入火热的DL领域 阅读全文                        ...

  4. python图像分类代码_Kaggle—So Easy!百行代码实现排名Top 5%的图像分类比赛

    Kaggle-So Easy!百行代码实现排名Top 5%的图像分类比赛 作者:七月在线彭老师 说明:本文最初由彭老师授权翟惠良发布在公众号"七月在线实验室"上,现再由July重新 ...

  5. Python百日百行代码挑战-day8,day9,day10,游戏实战系列-五子棋

    Python百日百行代码挑战-day8,day9,day10,游戏实战系列-五子棋 写在前面 需要用到的工具包和参考 游戏设定 初始化 切换下棋方 判断五子连珠(核心) 鼠标点击流程事件 成品展示 打 ...

  6. 100行代码写一个Compose版华容道

    之前写过几个 Compose 的 demo,但一直没使用到 Gesture, Theme 等特性,于是写了一个华容道的小程序来展示上述这些特性.写完后又一次被 Compose 的生产力所折服,整个程序 ...

  7. js 监听 安卓事件_百行代码实现js事件监听实现跨页面数据传输

    百行代码实现js事件监听实现跨页面数据传输 使用场景 类似消息队列的使用场景,支持同页面和跨页面通信,发送消息和接收消息 技术原理 跨页面通信: 基于事件监听,通过监听 storage事件监听回调机制 ...

  8. 鱼佬:百行代码入手数据挖掘赛!

    ↑↑↑关注后"星标"Datawhale 每日干货 & 每月组队学习,不错过 Datawhale干货 作者:鱼佬,武汉大学,Datawhale成员 本实践以科大讯飞xData ...

  9. 百行代码打造一个DI容器(支持瞬时生命周期、单利生命周期、构造函数自动注入、属性自动注入、字段自动注入)...

    DI注入在.Net平台是非常流行的, 很多项目都用到了,很多开发人员或多或少也用到DI容器了,感觉DI容器很神奇很厉害.本文将通过百行代码展示DI容器的内部核心代码(包括组件的瞬时生命周期.单利生命周 ...

最新文章

  1. [云炬创业基础笔记]第五章创业机会评估测试10
  2. 试用期java_Java 7试用资源
  3. Redis的N种妙用,不仅仅是缓存
  4. vnc服务器拼虚拟机,vnc连接虚拟机,7个步骤vnc连接虚拟机
  5. python转cython_Cython的简单使用
  6. 杭州市建筑物矢量数据(Shp格式+带高度)
  7. 嵌入式系统开发环境的构建08:在Hyper-V中安装Windows XP操作系统
  8. 掘金8000亿早教市场,启蒙APP们还面临哪些难题?
  9. 用LABwindows/CVI创建简单学生管理器
  10. react-native系列(24)API篇:屏幕宽高和屏幕像素密度
  11. 9.5 用算法和数学奠定专业基础——《逆袭大学》连载
  12. 创造力/创新思维的阻碍
  13. button run clicked becomes grey Android studio运行按钮变灰
  14. app后端 服务器端 后台 部署图
  15. kirin710f是什么处理器_我告诉你kirin710f是什么处理器
  16. 如何用Python将Word文档转换为Excel表格
  17. C++中表示正无穷与负无穷
  18. 周长最短面积最大_图说、故事趣说“周长一定时,何种封闭的平面图形面积最大?”...
  19. SDRAM,DDR1,DDR2,DDR3,DDR4的区别及其特点
  20. towhee+elasticsearch实现本地以图搜图

热门文章

  1. 手机短信如何实现实时传真通告
  2. 微信小程序1rpx border ios真机显示不全问题分析及解决方案
  3. python画五角星为什么144度_海龟编辑器五角星怎么画 绘制五角星就是这么简单...
  4. PBR 应用于虚幻引擎4贴图和材质创建的启示
  5. 微宝球型机器人功能_微宝球型机器人即将开售 酷炫玩法升级
  6. CentOS7搭建svn服务器
  7. Java新浪微博客户端开发第三步
  8. 魔力耳朵php,真实魔力耳朵怎么样?这些原因让我做出了选择
  9. 提交表单POST请求
  10. 2021-02-06 SONiC SAI结构 AdapterAdapter Host