iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Springboot如何通过lucene实现全文检索
  • 773
分享到

Springboot如何通过lucene实现全文检索

2023-07-02 08:07:57 773人浏览 安东尼
摘要

本篇内容主要讲解“SpringBoot如何通过lucene实现全文检索”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“springboot如何通过lucene实现全文检索”吧!Lucene提供了一

本篇内容主要讲解“SpringBoot如何通过lucene实现全文检索”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习springboot如何通过lucene实现全文检索”吧!

Lucene提供了一个简单却强大的应用程序接口(api),能够做全文索引和搜寻,在Java开发环境里Lucene是一个成熟的免费开放源代码工具

Lucene全文检索就是对文档中全部内容进行分词,然后对所有单词建立倒排索引的过程。主要操作是使用Lucene的API来实现对索引的增(创建索引)、删(删除索引)、改(修改索引)、查(搜索数据)。

假设我们的电脑的目录中含有很多文本文档,我们需要查找哪些文档含有某个关键词。为了实现这种功能,我们首先利用 Lucene 对这个目录中的文档建立索引,然后在建立好的索引中搜索我们所要查找的文档。通过这个例子读者会对如何利用 Lucene 构建自己的搜索应用程序有个比较清楚的认识。

建立索引

Document

Document 是用来描述文档的,这里的文档可以指一个 html 页面,一封电子邮件,或者是一个文本文件。一个 Document 对象由多个 Field 对象组成,可以把一个 Document 对象想象成数据库中的一个记录,而每个 Field 对象就是记录的一个字段。

Field

Field 对象是用来描述一个文档的某个属性的,比如一封电子邮件的标题和内容可以用两个 Field 对象分别描述。

Analyzer

在一个文档被索引之前,首先需要对文档内容进行分词处理,这部分工作就是由 Analyzer 来做的。Analyzer 类是一个抽象类,它有多个实现。针对不同的语言和应用需要选择适合的 Analyzer。Analyzer 把分词后的内容交给 IndexWriter 来建立索引。

IndexWriter

IndexWriter 是 Lucene 用来创建索引的一个核心的类,他的作用是把一个个的 Document 对象加到索引中来。

Directory

这个类代表了 Lucene 的索引的存储的位置,这是一个抽象类,它目前有两个实现,第一个是 FSDirectory,它表示一个存储在文件系统中的索引的位置。第二个是 RAMDirectory,它表示一个存储在内存当中的索引的位置。

检索文档

Query

这是一个抽象类,他有多个实现,比如 TerMQuery, BooleanQuery, PrefixQuery. 这个类的目的是把用户输入的查询字符串封装成 Lucene 能够识别的 Query。

Term

Term 是搜索的基本单位,一个 Term 对象有两个 String 类型的域组成。生成一个 Term 对象可以有如下一条语句来完成:Term term = new Term(“fieldName”,”queryWord”); 其中第一个参数代表了要在文档的哪一个 Field 上进行查找,第二个参数代表了要查询的关键词。

TermQuery

TermQuery 是抽象类 Query 的一个子类,它同时也是 Lucene 支持的最为基本的一个查询类。生成一个 TermQuery 对象由如下语句完成: TermQuery termQuery = new TermQuery(new Term(“fieldName”,”queryWord”)); 它的构造函数只接受一个参数,那就是一个 Term 对象。

IndexSearcher

IndexSearcher 是用来在建立好的索引上进行搜索的。它只能以只读的方式打开一个索引,所以可以有多个 IndexSearcher 的实例在一个索引上进行操作。

Hits

Hits 是用来保存搜索的结果的。

实例

pom依赖

<!-- lucene核心库 -->        <dependency>            <groupId>org.apache.lucene</groupId>            <artifactId>lucene-core</artifactId>            <version>7.6.0</version>        </dependency>        <!-- Lucene的查询解析器 -->        <dependency>            <groupId>org.apache.lucene</groupId>            <artifactId>lucene-queryparser</artifactId>            <version>7.6.0</version>        </dependency>        <!-- lucene的默认分词器库,适用于英文分词 -->        <dependency>            <groupId>org.apache.lucene</groupId>            <artifactId>lucene-analyzers-common</artifactId>            <version>7.6.0</version>        </dependency>        <!-- lucene的高亮显示 -->        <dependency>            <groupId>org.apache.lucene</groupId>            <artifactId>lucene-highlighter</artifactId>            <version>7.6.0</version>        </dependency>        <!-- smartcn中文分词器 -->        <dependency>            <groupId>org.apache.lucene</groupId>            <artifactId>lucene-analyzers-smartcn</artifactId>            <version>7.6.0</version>        </dependency>        <!-- ik分词器 -->        <dependency>            <groupId>com.janeluo</groupId>            <artifactId>ikanalyzer</artifactId>            <version>2012_u6</version>        </dependency>

自定义IK分词器

public class MyIKAnalyzer extends Analyzer {    private boolean useSmart;    public MyIKAnalyzer() {        this(false);    }    public MyIKAnalyzer(boolean useSmart) {        this.useSmart = useSmart;    }    @Override    protected TokenStreamComponents createComponents(String s) {        Tokenizer _MyIKTokenizer = new MyIKTokenizer(this.useSmart());        return new TokenStreamComponents(_MyIKTokenizer);    }    public boolean useSmart() {        return this.useSmart;    }    public void setUseSmart(boolean useSmart) {        this.useSmart = useSmart;    }}
public class MyIKTokenizer extends Tokenizer {    private IKSegmenter _IKImplement;    private final CharTermAttribute termAtt = (CharTermAttribute)this.addAttribute(CharTermAttribute.class);    private final OffsetAttribute offsetAtt = (OffsetAttribute)this.addAttribute(OffsetAttribute.class);    private final TypeAttribute typeAtt = (TypeAttribute)this.addAttribute(TypeAttribute.class);    private int endPosition;    //useSmart:设置是否使用智能分词。默认为false,使用细粒度分词,这里如果更改为TRUE,那么搜索到的结果可能就少的很多    public MyIKTokenizer(boolean useSmart) {        this._IKImplement = new IKSegmenter(this.input, useSmart);    }    @Override    public boolean incrementToken() throws IOException {        this.clearAttributes();        Lexeme nextLexeme = this._IKImplement.next();        if (nextLexeme != null) {            this.termAtt.append(nextLexeme.getLexemeText());            this.termAtt.setLength(nextLexeme.getLength());            this.offsetAtt.setOffset(nextLexeme.getBeginPosition(), nextLexeme.getEndPosition());            this.endPosition = nextLexeme.getEndPosition();            this.typeAtt.setType(nextLexeme.getLexemeTypeString());            return true;        } else {            return false;        }    }    @Override    public void reset() throws IOException {        super.reset();        this._IKImplement.reset(this.input);    }    @Override    public final void end() {        int finalOffset = this.correctOffset(this.endPosition);        this.offsetAtt.setOffset(finalOffset, finalOffset);    }}

测试1

@RequestMapping("/createIndex")    public String createIndex() throws IOException {        List<Content> list1 = new ArrayList<>();        list1.add(new Content(null, "Java面向对象", "10", null, "Java面向对象从入门到精通,简单上手"));        list1.add(new Content(null, "Java面向对象java", "10", null, "Java面向对象从入门到精通,简单上手"));        list1.add(new Content(null, "Java面向编程", "15", null, "Java面向对象编程书籍"));        list1.add(new Content(null, "javascript入门", "18", null, "JavaScript入门编程书籍"));        list1.add(new Content(null, "深入理解Java编程", "13", null, "十三四天掌握Java基础"));        list1.add(new Content(null, "从入门到放弃_Java", "20", null, "一门从入门到放弃的书籍"));        list1.add(new Content(null, "Head First Java", "30", null, "《Head First Java》是一本完整地面向对象(object-oriented,OO)程序设计和Java的学习指导用书"));        list1.add(new Content(null, "Java 核心技术:卷1 基础知识", "22", null, "全书共14章,包括Java基本的程序结构、对象与类、继承、接口与内部类、图形程序设计、事件处理、Swing用户界面组件"));        list1.add(new Content(null, "Java 编程思想", "12", null, "本书赢得了全球程序员的广泛赞誉,即使是最晦涩的概念,在Bruce Eckel的文字亲和力和小而直接的编程示例面前也会化解于无形"));        list1.add(new Content(null, "Java开发实战经典", "51", null, "本书是一本综合讲解Java核心技术的书籍,在书中使用大量的代码及案例进行知识点的分析与运用"));        list1.add(new Content(null, "Effective Java", "10", null, "本书介绍了在Java编程中57条极具实用价值的经验规则,这些经验规则涵盖了大多数开发人员每天所面临的问题的解决方案"));        list1.add(new Content(null, "分布式 Java 应用:基础与实践", "14", null, "本书介绍了编写分布式Java应用涉及的众多知识点,分为了基于Java实现网络通信、rpc;基于SOA实现大型分布式Java应用"));        list1.add(new Content(null, "Http权威指南", "11", null, "超文本传输协议(Hypertext Transfer Protocol,HTTP)是在万维网上进行通信时所使用的协议方案"));        list1.add(new Content(null, "Spring", "15", null, "这是啥,还需要学习吗?Java程序员必备书籍"));        list1.add(new Content(null, "深入理解 Java 虚拟机", "18", null, "作为一位Java程序员,你是否也曾经想深入理解Java虚拟机,但是却被它的复杂和深奥拒之门外"));        list1.add(new Content(null, "springboot实战", "11", null, "完成对于springboot的理解,是每个Java程序员必备的姿势"));        list1.add(new Content(null, "springMVC学习", "72", null, "springmvc学习指南"));        list1.add(new Content(null, "Vue入门到放弃", "20", null, "vue入门到放弃书籍信息"));        list1.add(new Content(null, "vue入门到精通", "20", null, "vue入门到精通相关书籍信息"));        list1.add(new Content(null, "vue之旅", "20", null, "由浅入深地全面介绍vue技术,包含大量案例与代码"));        list1.add(new Content(null, "vue实战", "20", null, "以实战为导向,系统讲解如何使用 "));        list1.add(new Content(null, "vue入门与实践", "20", null, "现已得到苹果、微软、谷歌等主流厂商全面支持"));        list1.add(new Content(null, "vue.js应用测试", "20", null, "Vue.js创始人尤雨溪鼎力推荐!Vue官方测试工具作者亲笔撰写,Vue.js应用测试完全学习指南"));        list1.add(new Content(null, "PHPMySQL web开发", "20", null, "本书是利用phpMysql构建数据库驱动的WEB应用程序的权威指南"));        list1.add(new Content(null, "Web高效编程与优化实践", "20", null, "从思想提升和内容修炼两个维度,围绕前端工程师必备的前端技术和编程基础"));        list1.add(new Content(null, "Vue.js 2.x实践指南", "20", null, "本书旨在让初学者能够快速上手vue技术栈,并能够利用所学知识独立动手进行项目开发"));        list1.add(new Content(null, "初始vue", "20", null, "解开vue的面纱"));        list1.add(new Content(null, "什么是vue", "20", null, "一步一步的了解vue相关信息"));        list1.add(new Content(null, "深入浅出vue", "20", null, "深入浅出vue,慢慢掌握"));        list1.add(new Content(null, "三天vue实战", "20", null, "三天掌握vue开发"));        list1.add(new Content(null, "不知火舞", "20", null, "不知名的vue"));        list1.add(new Content(null, "娜可露露", "20", null, "一招秒人"));        list1.add(new Content(null, "宫本武藏", "20", null, "我就是一个超级兵"));        list1.add(new Content(null, "vue宫本vue", "20", null, "我就是一个超级兵"));        // 创建文档的集合        Collection<Document> docs = new ArrayList<>();        for (int i = 0; i < list1.size(); i++) {            //contentMapper.insertSelective(list1.get(i));            // 创建文档对象            Document document = new Document();            //StringField会创建索引,但是不会被分词,TextField,即创建索引又会被分词。            document.add(new StringField("id", (i + 1) + "", Field.Store.YES));            document.add(new TextField("title", list1.get(i).getTitle(), Field.Store.YES));            document.add(new TextField("price", list1.get(i).getPrice(), Field.Store.YES));            document.add(new TextField("descs", list1.get(i).getDescs(), Field.Store.YES));            docs.add(document);        }        // 索引目录类,指定索引在硬盘中的位置,我的设置为D盘的indexDir文件夹        Directory directory = FSDirectory.open(FileSystems.getDefault().getPath("D:\\Lucene\\indexDir"));        // 引入IK分词器        Analyzer analyzer = new MyIKAnalyzer();        // 索引写出工具的配置对象,这个地方就是最上面报错的问题解决方案        IndexWriterConfig conf = new IndexWriterConfig(analyzer);        // 设置打开方式:OpenMode.APPEND 会在索引库的基础上追加新索引。OpenMode.CREATE会先清空原来数据,再提交新的索引        conf.setOpenMode(IndexWriterConfig.OpenMode.CREATE);        // 创建索引的写出工具类。参数:索引的目录和配置信息        IndexWriter indexWriter = new IndexWriter(directory, conf);        // 把文档集合交给IndexWriter        indexWriter.aDDDocuments(docs);        // 提交        indexWriter.commit();        // 关闭        indexWriter.close();        return "success";    }    @RequestMapping("/updateIndex")    public String update(String age) throws IOException {        // 创建目录对象        Directory directory = FSDirectory.open(FileSystems.getDefault().getPath("D:\\Lucene\\indexDir"));        // 创建配置对象        IndexWriterConfig conf = new IndexWriterConfig(new MyIKAnalyzer());        // 创建索引写出工具        IndexWriter writer = new IndexWriter(directory, conf);        // 创建新的文档数据        Document doc = new Document();        doc.add(new StringField("id", "34", Field.Store.YES));        //Content content = contentMapper.selectByPrimaryKey("34");        //content.setTitle("宫本武藏超级兵");        //contentMapper.updateByPrimaryKeySelective(content);        Content content = new Content(34, "宫本武藏超级兵", "", "", "");        doc.add(new TextField("title", content.getTitle(), Field.Store.YES));        doc.add(new TextField("price", content.getPrice(), Field.Store.YES));        doc.add(new TextField("descs", content.getDescs(), Field.Store.YES));        writer.updateDocument(new Term("id", "34"), doc);        // 提交        writer.commit();        // 关闭        writer.close();        return "success";    }    @RequestMapping("/deleteIndex")    public String deleteIndex() throws IOException {        // 创建目录对象        Directory directory = FSDirectory.open(FileSystems.getDefault().getPath("D:\\Lucene\\indexDir"));        // 创建配置对象        IndexWriterConfig conf = new IndexWriterConfig(new IKAnalyzer());        // 创建索引写出工具        IndexWriter writer = new IndexWriter(directory, conf);        // 根据词条进行删除        writer.deleteDocuments(new Term("id", "34"));        // 提交        writer.commit();        // 关闭        writer.close();        return "success";    }    @RequestMapping("/searchText")    public Object searchText(String text, httpservletRequest request) throws IOException, ParseException {        Directory directory = FSDirectory.open(FileSystems.getDefault().getPath("D:\\Lucene\\indexDir"));        // 索引读取工具        IndexReader reader = DirectoryReader.open(directory);        // 索引搜索工具        IndexSearcher searcher = new IndexSearcher(reader);        // 创建查询解析器,两个参数:默认要查询的字段的名称,分词器        QueryParser parser = new QueryParser("descs", new MyIKAnalyzer());        // 创建查询对象        Query query = parser.parse(text);        // 获取前十条记录        TopDocs topDocs = searcher.search(query, 10);        // 获取总条数        System.out.println("本次搜索共找到" + topDocs.totalHits + "条数据");        // 获取得分文档对象(ScoreDoc)数组.SocreDoc中包含:文档的编号、文档的得分        ScoreDoc[] scoreDocs = topDocs.scoreDocs;        List<Content> list = new ArrayList<>();        for (ScoreDoc scoreDoc : scoreDocs) {            // 取出文档编号            int docID = scoreDoc.doc;            // 根据编号去找文档            Document doc = reader.document(docID);            //Content content = contentMapper.selectByPrimaryKey(doc.get("id"));            Content content = new Content();            content.setId(Integer.valueOf(doc.get("id")));            content.setTitle(doc.get("title"));            content.setDescs(doc.get("descs"));            list.add(content);        }        return list;    }    @RequestMapping("/searchText1")    public Object searchText1(String text, HttpServletRequest request) throws IOException, ParseException {        String[] str = {"title", "descs"};        Directory directory = FSDirectory.open(FileSystems.getDefault().getPath("d:\\indexDir"));        // 索引读取工具        IndexReader reader = DirectoryReader.open(directory);        // 索引搜索工具        IndexSearcher searcher = new IndexSearcher(reader);        // 创建查询解析器,两个参数:默认要查询的字段的名称,分词器        MultiFieldQueryParser parser = new MultiFieldQueryParser(str, new MyIKAnalyzer());        // 创建查询对象        Query query = parser.parse(text);        // 获取前十条记录        TopDocs topDocs = searcher.search(query, 100);        // 获取总条数        System.out.println("本次搜索共找到" + topDocs.totalHits + "条数据");        // 获取得分文档对象(ScoreDoc)数组.SocreDoc中包含:文档的编号、文档的得分        ScoreDoc[] scoreDocs = topDocs.scoreDocs;        List<Content> list = new ArrayList<>();        for (ScoreDoc scoreDoc : scoreDocs) {            // 取出文档编号            int docID = scoreDoc.doc;            // 根据编号去找文档            Document doc = reader.document(docID);            //Content content = contentMapper.selectByPrimaryKey(doc.get("id"));            Content content = new Content();            content.setId(Integer.valueOf(doc.get("id")));            list.add(content);        }        return list;    }    @RequestMapping("/searchText2")    public Object searchText2(String text, HttpServletRequest request) throws IOException, ParseException, InvalidTokenOffsetsException {        String[] str = {"title", "descs"};        Directory directory = FSDirectory.open(FileSystems.getDefault().getPath("d:\\indexDir"));        // 索引读取工具        IndexReader reader = DirectoryReader.open(directory);        // 索引搜索工具        IndexSearcher searcher = new IndexSearcher(reader);        // 创建查询解析器,两个参数:默认要查询的字段的名称,分词器        MultiFieldQueryParser parser = new MultiFieldQueryParser(str, new MyIKAnalyzer());        // 创建查询对象        Query query = parser.parse(text);        // 获取前十条记录        TopDocs topDocs = searcher.search(query, 100);        // 获取总条数        System.out.println("本次搜索共找到" + topDocs.totalHits + "条数据");        //高亮显示        SimpleHTMLFORMatter simpleHTMLFormatter = new SimpleHTMLFormatter("<span style='color:red'>", "</span>");        Highlighter highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(query));        Fragmenter fragmenter = new SimpleFragmenter(100);   //高亮后的段落范围在100字内        highlighter.setTextFragmenter(fragmenter);        // 获取得分文档对象(ScoreDoc)数组.SocreDoc中包含:文档的编号、文档的得分        ScoreDoc[] scoreDocs = topDocs.scoreDocs;        List<Content> list = new ArrayList<>();        for (ScoreDoc scoreDoc : scoreDocs) {            // 取出文档编号            int docID = scoreDoc.doc;            // 根据编号去找文档            Document doc = reader.document(docID);            //Content content = contentMapper.selectByPrimaryKey(doc.get("id"));            Content content = new Content();            //处理高亮字段显示            String title = highlighter.getBestFragment(new MyIKAnalyzer(), "title", doc.get("title"));            if (title == null) {                title = content.getTitle();            }            String descs = highlighter.getBestFragment(new MyIKAnalyzer(), "descs", doc.get("descs"));            if (descs == null) {                descs = content.getDescs();            }            content.setDescs(descs);            content.setTitle(title);            list.add(content);        }        request.setAttribute("list", list);        return "index";    }    @RequestMapping("/searchText3")    public String searchText3(String text, HttpServletRequest request) throws IOException, ParseException, InvalidTokenOffsetsException {        String[] str = {"title", "descs"};        int page = 1;        int pageSize = 10;        Directory directory = FSDirectory.open(FileSystems.getDefault().getPath("d:\\indexDir"));        // 索引读取工具        IndexReader reader = DirectoryReader.open(directory);        // 索引搜索工具        IndexSearcher searcher = new IndexSearcher(reader);        // 创建查询解析器,两个参数:默认要查询的字段的名称,分词器        MultiFieldQueryParser parser = new MultiFieldQueryParser(str, new MyIKAnalyzer());        // 创建查询对象        Query query = parser.parse(text);        // 获取前十条记录        //TopDocs topDocs = searcher.search(query, 100);        TopDocs topDocs = searchByPage(page, pageSize, searcher, query);        // 获取总条数        System.out.println("本次搜索共找到" + topDocs.totalHits + "条数据");        //高亮显示        SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<span style='color:red'>", "</span>");        Highlighter highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(query));        Fragmenter fragmenter = new SimpleFragmenter(100);   //高亮后的段落范围在100字内        highlighter.setTextFragmenter(fragmenter);        // 获取得分文档对象(ScoreDoc)数组.SocreDoc中包含:文档的编号、文档的得分        ScoreDoc[] scoreDocs = topDocs.scoreDocs;        List<Content> list = new ArrayList<>();        for (ScoreDoc scoreDoc : scoreDocs) {            // 取出文档编号            int docID = scoreDoc.doc;            // 根据编号去找文档            Document doc = reader.document(docID);            //Content content = contentMapper.selectByPrimaryKey(doc.get("id"));            Content content = new Content();            //处理高亮字段显示            String title = highlighter.getBestFragment(new MyIKAnalyzer(), "title", doc.get("title"));            if (title == null) {                title = content.getTitle();            }            String descs = highlighter.getBestFragment(new MyIKAnalyzer(), "descs", doc.get("descs"));            if (descs == null) {                descs = content.getDescs();            }            content.setDescs(descs);            content.setTitle(title);            list.add(content);        }        System.err.println("list的长度:" + list.size());        request.setAttribute("page", page);        request.setAttribute("pageSize", pageSize);        request.setAttribute("list", list);        return "index";    }    private TopDocs searchByPage(int page, int perPage, IndexSearcher searcher, Query query) throws IOException {        TopDocs result = null;        if (query == null) {            System.out.println(" Query is null return null ");            return null;        }        ScoreDoc before = null;        if (page != 1) {            TopDocs docsBefore = searcher.search(query, (page - 1) * perPage);            ScoreDoc[] scoreDocs = docsBefore.scoreDocs;            if (scoreDocs.length > 0) {                before = scoreDocs[scoreDocs.length - 1];            }        }        result = searcher.searchAfter(before, query, perPage);        return result;    }    @RequestMapping("/searchText4")    public String searchText4(String text, HttpServletRequest request) throws IOException, ParseException, InvalidTokenOffsetsException {        String[] str = {"title", "descs"};        int page = 1;        int pageSize = 100;        IndexSearcher searcher = getMoreSearch("d:\\indexDir");        // 创建查询解析器,两个参数:默认要查询的字段的名称,分词器        MultiFieldQueryParser parser = new MultiFieldQueryParser(str, new MyIKAnalyzer());        // 创建查询对象        Query query = parser.parse(text);        TopDocs topDocs = searchByPage(page, pageSize, searcher, query);        // 获取总条数        System.out.println("本次搜索共找到" + topDocs.totalHits + "条数据");        //高亮显示        SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<span style='color:red'>", "</span>");        Highlighter highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(query));        Fragmenter fragmenter = new SimpleFragmenter(100);   //高亮后的段落范围在100字内        highlighter.setTextFragmenter(fragmenter);        // 获取得分文档对象(ScoreDoc)数组.SocreDoc中包含:文档的编号、文档的得分        ScoreDoc[] scoreDocs = topDocs.scoreDocs;        List<Content> list = new ArrayList<>();        for (ScoreDoc scoreDoc : scoreDocs) {            // 取出文档编号            int docID = scoreDoc.doc;            // 根据编号去找文档            //Document doc = reader.document(docID);            Document doc = searcher.doc(docID);//多索引找文档要用searcher找了,reader容易报错            //Content content = contentMapper.selectByPrimaryKey(doc.get("id"));            Content content = new Content();            //处理高亮字段显示            String title = highlighter.getBestFragment(new MyIKAnalyzer(), "title", doc.get("title"));            if (title == null) {                title = content.getTitle();            }            String descs = highlighter.getBestFragment(new MyIKAnalyzer(), "descs", doc.get("descs"));            if (descs == null) {                descs = content.getDescs();            }            content.setDescs(descs);            content.setTitle(title);            list.add(content);        }        System.err.println("list的长度:" + list.size());        request.setAttribute("page", page);        request.setAttribute("pageSize", pageSize);        request.setAttribute("list", list);        return "index";    }    private IndexSearcher getMoreSearch(String string) {        MultiReader reader = null;        //设置        try {            File[] files = new File(string).listFiles();            IndexReader[] readers = new IndexReader[files.length];            for (int i = 0; i < files.length; i++) {                readers[i] = DirectoryReader.open(FSDirectory.open(Paths.get(files[i].getPath(), new String[0])));            }            reader = new MultiReader(readers);        } catch (IOException e) {            e.printStackTrace();        }        return new IndexSearcher(reader);        //如果索引文件过多,可以这样加快效率            }

测试2

public static void main(String[] args) throws IOException, ParseException {        long startTime = System.currentTimeMillis();        // indexDir is the directory that hosts Lucene's index files        File indexDir = new File("D:\\Lucene\\indexDir");        // dataDir is the directory that hosts the text files that to be indexed        File dataDir = new File("D:\\Lucene\\dataDir");        Analyzer luceneAnalyzer = new StandardAnalyzer();        // 或引入IK分词器        Analyzer IkAnalyzer = new MyIKAnalyzer();        Directory directory = FSDirectory.open(FileSystems.getDefault().getPath("D:\\Lucene\\indexDir"));        IndexWriterConfig indexWriterConfig = new IndexWriterConfig(IkAnalyzer);        // 设置打开方式:OpenMode.APPEND 会在索引库的基础上追加新索引、OpenMode.CREATE会先清空原来数据,再提交新的索引        indexWriterConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE);        IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);        File[] dataFiles = dataDir.listFiles();        for (int i = 0; i < dataFiles.length; i++) {            if (dataFiles[i].isFile() && dataFiles[i].getName().endsWith(".txt")) {                System.out.println("Indexing file " + dataFiles[i].getCanonicalPath());                Document document = new Document();                Reader txtReader = new FileReader(dataFiles[i]);                document.add(new TextField("path", dataFiles[i].getCanonicalPath(), Field.Store.YES));                document.add(new TextField("contents", txtReader));                indexWriter.addDocument(document);            }        }        indexWriter.commit();        indexWriter.close();        long endTime = System.currentTimeMillis();        System.out.println("It takes "                + (endTime - startTime)                + " milliseconds to create index for the files in directory "                + dataDir.getPath());        String queryStr = "hello";        // 索引读取工具        IndexReader indexReader = DirectoryReader.open(directory);        // 索引搜索工具        IndexSearcher indexSearcher = new IndexSearcher(indexReader);        // 创建查询解析器,两个参数:默认要查询的字段的名称,分词器        QueryParser parser = new QueryParser("contents", IkAnalyzer);        // 创建查询对象        Query query = parser.parse(queryStr);        // 获取前十条记录        TopDocs topDocs = indexSearcher.search(query, 10);        // 获取总条数        System.out.println("本次搜索共找到" + topDocs.totalHits + "条数据");        // 获取得分文档对象(ScoreDoc)数组.SocreDoc中包含:文档的编号、文档的得分        ScoreDoc[] scoreDocs = topDocs.scoreDocs;        for (ScoreDoc scoreDoc : scoreDocs) {            // 取出文档编号            int docID = scoreDoc.doc;            // 根据编号去找文档            Document doc = indexReader.document(docID);            System.out.println(doc.get("path"));        }    }

IndexWriter对象将dataDir下的所有txt文件建立索引,指定索引文件的目录为indexDir,Document对象对应一个带搜索的文件,可以是文本文件也可以是一个网页,为Document对象指定field,这里为文本文件定义了两个field:path和contents,运行完第一部分代码后,则在指定目录下生成了索引文件,如下

Springboot如何通过lucene实现全文检索

IndexReader对象读取索引文件,通过QueryParser对象指定语法分析器和对document的那个字段进行查询,Query对象则制定了搜索的关键字,通过IndexSearcher对象实现检索,并返回结果集TopDocs,运行完第二部分代码后,会看到打印包含关键字的文本文件的路径,如下

Springboot如何通过lucene实现全文检索

到此,相信大家对“Springboot如何通过lucene实现全文检索”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: Springboot如何通过lucene实现全文检索

本文链接: https://www.lsjlt.com/news/340626.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Springboot如何通过lucene实现全文检索
    本篇内容主要讲解“Springboot如何通过lucene实现全文检索”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Springboot如何通过lucene实现全文检索”吧!Lucene提供了一...
    99+
    2023-07-02
  • Springboot通过lucene实现全文检索详解流程
    目录建立索引检索文档Lucene提供了一个简单却强大的应用程序接口(API),能够做全文索引和搜寻,在Java开发环境里Lucene是一个成熟的免费开放源代码工具。 Lucene全文...
    99+
    2024-04-02
  • 【springboot微服务】Lucence实现Mysql全文检索
    目录 一、前言 1.1 常规调优手段 1.1.1 加索引 1.1.2 代码层优化 1.1.3 减少关联表查询来源地址:https://blog.csdn.net/zhangcongyi420/article/details/12994081...
    99+
    2023-09-25
    lucence实现全文索引 lucence优化数据库查询 lucence结合mysql
  • 如何基于solr实现全文检索
    这篇文章将为大家详细讲解有关如何基于solr实现全文检索,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口。用户可以...
    99+
    2023-05-30
    solr
  • springboot微服务Lucence实现Mysql全文检索功能
    目录一、前言1.1 常规调优手段1.1.1 加索引1.1.2 代码层优化1.1.3 减少关联表查询1.1.4 分库分表1.1.5 引入第三方存储二、一个棘手的问题2.1 前置准备2...
    99+
    2023-04-11
    Mysql全文检索 springboot微服务全文检索
  • MySQL 全文检索的实现
    微信搜「古时的风筝」,还有更多技术干货 这有朋友聊到他们的系统中要接入全文检索,这让我想起了很久以前为一个很古老的项目添加搜索功能的事儿。 一提到全文检索,我们首先就会想到搜索引擎。也就是用一个...
    99+
    2023-09-16
    全文检索 mysql 数据库
  • 如何通过索引优化PHP与MySQL的全文检索和排序查询?
    在开发互联网应用程序中,全文检索和排序查询是常见的需求。对于大量数据的查询操作来说,优化索引是提高数据库性能的重要手段之一。在PHP与MySQL的组合中,我们可以通过合理使用索引,来提高全文检索和排序查询的效率。本文将介绍如何通过索引优化P...
    99+
    2023-10-21
    MySQL PHP 索引优化
  • 如何用Lucene.net全文检索实现仿造百度
    本篇文章为大家展示了如何用Lucene.net全文检索实现仿造百度,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Lucene.NetLucene.net是Lucene的.net移植版本,是一个开源的...
    99+
    2023-06-17
  • ​ElasticSearch怎么实现分词全文检索
    Elasticsearch是一个基于Lucene的搜索引擎,它提供了强大的全文搜索和分析能力。要实现分词全文检索,你可以按照以下步骤...
    99+
    2023-10-21
    ​ElasticSearch
  • lucene全文搜索怎么实现数据库的like匹配效果
    本篇内容介绍了“lucene全文搜索怎么实现数据库的like匹配效果”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一般情况下,全文搜索是通过...
    99+
    2023-06-26
  • 如何通过索引提升PHP与MySQL的大数据查询和全文检索的效率?
    在面对大数据量的查询和全文检索时,PHP和MySQL是广泛使用的组合。然而,随着数据量的增加,查询和检索的效率可能会下降。为了提高效率,我们可以利用索引来加快查询和检索的速度。本文将介绍如何通过索引来优化PHP与MySQL的大数据查询和全文...
    99+
    2023-10-21
    MySQL PHP 索引
  • Java如何实现文件检索系统
    这篇文章主要介绍了Java如何实现文件检索系统的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java如何实现文件检索系统文章都会有所收获,下面我们一起来看看吧。示例代码package Demo;imp...
    99+
    2023-07-02
  • 利用Lucene如何实现布尔搜索功能
    本篇文章给大家分享的是有关利用Lucene如何实现布尔搜索功能,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。什么是luceneLucene是apache软件基金会jakarta...
    99+
    2023-05-31
    lucene 布尔搜索
  • 如何使用MySQL的全文检索功能实现高效率的文本搜索?
    如何使用MySQL的全文检索功能实现高效率的文本搜索?作者:AI助手摘要:本文介绍了如何使用MySQL的全文检索功能,在数据库中实现高效率的文本搜索。首先,我们会讲解MySQL全文索引的基本原理和使用方法。然后,我们会探讨如何优化全文检索的...
    99+
    2023-10-22
    MySQL 全文检索 文本搜索
  • Django对接elasticsearch怎么实现全文检索
    这篇文章主要讲解了“Django对接elasticsearch怎么实现全文检索”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Django对接elasticsearch怎么实现全文检索”吧!目...
    99+
    2023-06-20
  • MariaDB中如何处理文本搜索和全文检索
    在MariaDB中处理文本搜索和全文检索可以通过使用全文索引和全文搜索函数来实现。以下是一些处理文本搜索和全文检索的方法: 1、创建...
    99+
    2024-04-02
  • RiSearch PHP 实现站内搜索的全文检索方案
    随着互联网的发展,网站的内容和数据量越来越庞大,传统的数据库查询已经不能满足快速搜索的需求。为了提升用户体验和提高网站的搜索效率,全文检索技术应运而生。RiSearch是一种基于PHP的全文检索引擎,它为我们提供了一种高效、简单的站内搜索解...
    99+
    2023-10-21
    PHP 全文检索 RiSearch
  • SQLServer数据库中怎么实现全文检索
    今天就跟大家聊聊有关SQLServer数据库中怎么实现全文检索,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。  SQLServer数据库怎么实现全文...
    99+
    2024-04-02
  • Sphinx PHP 实现全文搜索的中文分词与检索优化
    引言:随着互联网的发展和信息爆炸的时代,全文搜索引擎成为了人们进行信息检索的重要工具。传统的全文搜索引擎主要针对英文等西方语言进行优化,而对于中文这种特殊的语言来说,传统的全文搜索引擎存在一些问题。本文将介绍如何利用Sphinx PHP实现...
    99+
    2023-10-21
    Sphinx - A software library used for performing full-text se
  • 如何使用PostgreSQL进行中文全文检索
    目录开始安装插件启动配置Host权限服务器配置分词SCWSzhpaserSQL优化添加自定义词典扩展总结开始 安装 首先是安装 PgSQL,这里我使用的是 PgSQL 9.6,PgS...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作