前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Lucene全文检索工具包学习笔记总结

Lucene全文检索工具包学习笔记总结

作者头像
全栈程序员站长
发布2022-06-30 10:30:13
4430
发布2022-06-30 10:30:13
举报
文章被收录于专栏:全栈程序员必看

Lucene—-全文检索的工具包 隶属于apache(solr也是属于apache,solr底层的实现是Lucene)

一、数据的分类: 结构化数据 具有固定类型和长度的数据 比如:数据库(mysql/oracl)中的数据,元数据(windows中的文件)

代码语言:javascript
复制
非结构化数据
    没有固定类型和长度的数据
    比如:邮件/word里面的数据

二、数据查找的方式 结构化数据 数据库中数据通过sql语句可以搜索 元数据(windows中的)通过windows提供的搜索栏进行搜索 非结构化数据 Word文档使用ctrl+F来搜索 顺序查找法(效率低,只要文档中有一定就能够找到) 全文检索(倒排查找),类似于字典查找方式 三、全文检索 含义: 把文件中的内容提取出来,把文件一个一个划分成词组(分), 把词组组装成索引,在进行搜索的时候先对索引进行搜索, 通过索引在去查找文档,这个过程叫全文搜索 优点:搜索快,效率高 缺点:使用空间去换取时间。 全文检索模仿的是字典查找

四、Lucene 1.含义: Lucene是一个全文检索的工具包(jar); 通过Lucene可以构建一个全文检索系统。 全文检索系统:就是能在tomcat下独立运行的war包, 对外提供全文检索的服务。

代码语言:javascript
复制
2.应用领域:
    (1)互联网全文检索(比如baidu/goole等搜索引擎);
    (2)站内全文检索(比如:淘宝、jd站内搜索);
    (3)优化数据库(like模糊查询,使用的是顺序查找,查询慢);

3.Lucene结构:
    (类似于字典)
    Lucene结构=索引+Document文档(可以有多个);

4.Document文档对象
    先要获取文档,然后创建文档对象Document;
    Document对象里面包含了[域名name;域值value]形式的键值对,我们成为Field(域);
    Field可以存储文件名称、文件大小、文件类型、文件存储的路径、文件里面的内容等;
    比如:一个document就是数据库中的一条数据,一个Field对应数据库中的一行一列
    注意:
        (1)创建好文档对象之后,我们需要对文档对象进行分词,
           这里使用什么分词器,在查询的时候也要使用同样的分词器
        (2)每个Document可以有多个Field,不同的Document可以有不同的Field,
           同一个Document可以有相同的Field(域名和域值都相同)

5.分词
    就是把提取的文档对象进行一个一个词组拆分;
    拆分的时候需要去掉停用词(a, an, the ,的, 地, 得, 啊, 嗯 ,呵呵),
    因为搜索的时候搜索这些词没有意义,将句子拆分成词,去掉标点符号和空格
    得到词叫做词元(term)

五、Document文档对象中的Field域

六、创建索引的流程 获取需要创建索引的文件—->穿件Document对象—->进行分词 —->创建索引写对象 —->将文档加入到索引和文档的写对象中 —->索引写对象提交和关闭索引写对象流 @Test public void testIndexManager() throws Exception { List documents = new ArrayList<>();//创建文档对象集合 //读取需要创建索引的文件 File f = new File(“D:\Indexsearchsource”); for (File file : f.listFiles()) { //文件名 String fileName = file.getName(); //文件内容 String fileContent = FileUtils.readFileToString(file); //文件大小 Long fileSize = FileUtils.sizeOf(file);

代码语言:javascript
复制
         //把文件名 文件内容 文件大小 放入到Field域中
         TextField nameField = new TextField("fileName", fileName, Store.YES);
         TextField contentField = new TextField("fileContent", fileContent, Store.YES);
         LongField sizeField = new LongField("fileSize", fileSize, Store.YES);

         //把域放入到文档Document对象中
         Document document = new Document();
         document.add(nameField);
         document.add(contentField);
         document.add(sizeField);

         //放入到一个document集合中
         documents.add(document);
    }
     //创建分词器
     //Analyzer analyzer = new StandardAnalyzer();//标准分词器
     Analyzer analyzer = new IKAnalyzer();//IK中文分词器

     //索引放的位置  FS----磁盘  RAM----内存
     Directory directory = FSDirectory.open(new File("d:\\indexDir"));

     //写对象的配置  使用什么分词器  lucene版本
     IndexWriterConfig conf = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);

     //创建索引写对象
     IndexWriter indexWriter = new IndexWriter(directory, conf);

     for (Document document : documents) {
        indexWriter.addDocument(document);
    }

     indexWriter.commit();
     indexWriter.close();
}

七、全文检索删除 删除索引使用的IndexWriter对象 所以分词器需要和创建索引的时候保持一致

代码语言:javascript
复制
删除所有indexWriter.deleteAll();
根据某个词元进行删除indexWriter.deleteDocuments(new Term("fileName", "apache"));


@Test
public void testIndexDel() throws Exception{
    //创建分词器,StandardAnalyzer标准分词器,标准分词器对英文分词效果很好,对中文是单字分词
    Analyzer analyzer = new IKAnalyzer();
    //指定索引和文档存储的目录
    Directory directory = FSDirectory.open(new File("E:\\dic"));
    //创建写对象的初始化对象
    IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);
    //创建索引和文档写对象
    IndexWriter indexWriter = new IndexWriter(directory, config);

    //删除所有
    //indexWriter.deleteAll();

    //根据名称进行删除
    //Term词元,就是一个词, 第一个参数:域名, 第二个参数:要删除含有此关键词的数据
    indexWriter.deleteDocuments(new Term("fileName", "apache"));

    //提交
    indexWriter.commit();
    //关闭
    indexWriter.close();
}

八、全文检索修改

代码语言:javascript
复制
/**
 * 更新就是按照传入的Term进行搜索,如果找到结果那么删除,将更新的内容重新生成一个Document对象
 * 如果没有搜索到结果,那么将更新的内容直接添加一个新的Document对象
 * @throws Exception
 */
@Test
public void testIndexUpdate() throws Exception{
    //创建分词器,StandardAnalyzer标准分词器,标准分词器对英文分词效果很好,对中文是单字分词
    Analyzer analyzer = new IKAnalyzer();
    //指定索引和文档存储的目录
    Directory directory = FSDirectory.open(new File("E:\\dic"));
    //创建写对象的初始化对象
    IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);
    //创建索引和文档写对象
    IndexWriter indexWriter = new IndexWriter(directory, config);


    //根据文件名称进行更新
    Term term = new Term("fileName", "web");
    //更新的对象
    Document doc = new Document();
    doc.add(new TextField("fileName", "xxxxxx", Store.YES));
    doc.add(new TextField("fileContext", "think in java xxxxxxx", Store.NO));
    doc.add(new LongField("fileSize", 100L, Store.YES));

    //更新
    indexWriter.updateDocument(term, doc);

    //提交
    indexWriter.commit();
    //关闭
    indexWriter.close();
}

九、全文检索查询(重点) TermQuery: 根据词进行搜索(只能从文本中进行搜索) QueryParser: 根据域名进行搜索,可以设置默认搜索域,推荐使用. (只能从文本中进行搜索) NumericRangeQuery: 从数值范围进行搜索 BooleanQuery: 组合查询,可以设置组合条件,not and or.从多个域中进行查询 must相当于and关键字,是并且的意思 should,相当于or关键字或者的意思 must_not相当于not关键字, 非的意思 注意:单独使用must_not 或者 独自使用must_not没有任何意义 MatchAllDocsQuery: 查询出所有文档 MultiFieldQueryParser:

可以从多个域中进行查询,只有这些域中有关键词的存在就查询出来.

代码语言:javascript
复制
@Test
public void testIndexSearch() throws Exception {
    // 创建查询的分词器要和创建索引的分词器保持一致
    Analyzer analyzer = new IKAnalyzer();
    // 目录对象
    Directory directory = FSDirectory.open(new File("d:\\indexDir"));
    // 创建读的索引对象
    IndexReader indexReader = IndexReader.open(directory);

    // 创建索引搜索对象
    IndexSearcher indexSearcher = new IndexSearcher(indexReader);

    // 创建查询对象,第一个参数:默认搜索域, 第二个参数:分词器
    // 默认搜索域作用:如果搜索语法中指定域名从指定域中搜索,
    // 如果搜索时只写了查询关键字,则从默认搜索域中进行搜索
    QueryParser queryParser = new QueryParser("fileContent", analyzer);
    // 查询语法=域名:搜索的关键字
    Query query = queryParser.parse("fileName:apache");

    TopDocs topDocs = indexSearcher.search(query, 5);
    System.out.println("一共搜索到多少条记录====" + topDocs.totalHits);

    // 从搜索结果对象中获取结果集
    ScoreDoc[] scoreDocs = topDocs.scoreDocs;
    for (ScoreDoc scoreDoc : scoreDocs) {
        int docId = scoreDoc.doc;// 索引的id
        // 通过文档ID从硬盘中读取出对应的文档
        Document document = indexReader.document(docId);
        String fileName = document.get("fileName");
        String fileContent = document.get("fileContent");
        String fileSize = document.get("fileSize");
        System.out.println(fileName);
        //System.out.println(fileContent);
        System.out.println(fileSize);
        System.out.println("==============");
    }
}

@Test
public void testIndexTermQuery() throws Exception{
    //创建分词器(创建索引和所有时所用的分词器必须一致)
    Analyzer analyzer = new IKAnalyzer();

    //创建词元:就是词,   
    Term term = new Term("fileName", "apache");
    //使用TermQuery查询,根据term对象进行查询
    TermQuery termQuery = new TermQuery(term);


    //指定索引和文档的目录
    Directory dir = FSDirectory.open(new File("E:\\dic"));
    //索引和文档的读取对象
    IndexReader indexReader = IndexReader.open(dir);
    //创建索引的搜索对象
    IndexSearcher indexSearcher = new IndexSearcher(indexReader);
    //搜索:第一个参数为查询语句对象, 第二个参数:指定显示多少条
    TopDocs topdocs = indexSearcher.search(termQuery, 5);
    //一共搜索到多少条记录
    System.out.println("=====count=====" + topdocs.totalHits);
    //从搜索结果对象中获取结果集
    ScoreDoc[] scoreDocs = topdocs.scoreDocs;

    for(ScoreDoc scoreDoc : scoreDocs){
        //获取docID
        int docID = scoreDoc.doc;
        //通过文档ID从硬盘中读取出对应的文档
        Document document = indexReader.document(docID);
        //get域名可以取出值 打印
        System.out.println("fileName:" + document.get("fileName"));
        System.out.println("fileSize:" + document.get("fileSize"));
        System.out.println("===================================");
    }
}
@Test
public void testNumericRangeQuery() throws Exception{
    //创建分词器(创建索引和所有时所用的分词器必须一致)
    Analyzer analyzer = new IKAnalyzer();

    //根据数字范围查询
    //查询文件大小,大于100 小于1000的文章
    //第一个参数:域名      
    //第二个参数:最小值,  
    //第三个参数:最大值, 
    //第四个参数:是否包含最小值,   
    //第五个参数:是否包含最大值
    Query query = NumericRangeQuery.newLongRange("fileSize", 100L, 1000L, true, true);      

    //指定索引和文档的目录
    Directory dir = FSDirectory.open(new File("E:\\dic"));
    //索引和文档的读取对象
    IndexReader indexReader = IndexReader.open(dir);
    //创建索引的搜索对象
    IndexSearcher indexSearcher = new IndexSearcher(indexReader);
    //搜索:第一个参数为查询语句对象, 第二个参数:指定显示多少条
    TopDocs topdocs = indexSearcher.search(query, 5);
    //一共搜索到多少条记录
    System.out.println("=====count=====" + topdocs.totalHits);
    //从搜索结果对象中获取结果集
    ScoreDoc[] scoreDocs = topdocs.scoreDocs;

    for(ScoreDoc scoreDoc : scoreDocs){
        //获取docID
        int docID = scoreDoc.doc;
        //通过文档ID从硬盘中读取出对应的文档
        Document document = indexReader.document(docID);
        //get域名可以取出值 打印
        System.out.println("fileName:" + document.get("fileName"));
        System.out.println("fileSize:" + document.get("fileSize"));
        System.out.println("====================================");
    }
}

@Test
public void testBooleanQuery() throws Exception{
    //创建分词器(创建索引和所有时所用的分词器必须一致)
    Analyzer analyzer = new IKAnalyzer();

    //布尔查询,就是可以根据多个条件组合进行查询
    //文件名称包含apache的,并且文件大小大于等于100 小于等于1000字节的文章
    BooleanQuery query = new BooleanQuery();

    //根据数字范围查询
    //查询文件大小,大于100 小于1000的文章
    //第一个参数:域名      
    //第二个参数:最小值,  
    //第三个参数:最大值, 
    //第四个参数:是否包含最小值,   
    //第五个参数:是否包含最大值
    Query numericQuery = NumericRangeQuery.newLongRange("fileSize", 100L, 1000L, true, true);

    //创建词元:就是词,   
    Term term = new Term("fileName", "apache");
    //使用TermQuery查询,根据term对象进行查询
    TermQuery termQuery = new TermQuery(term);

    //Occur是逻辑条件
    //must相当于and关键字,是并且的意思
    //should,相当于or关键字或者的意思
    //must_not相当于not关键字, 非的意思
    //注意:单独使用must_not  或者 独自使用must_not没有任何意义
    query.add(termQuery, Occur.MUST);
    query.add(numericQuery, Occur.MUST);

    //指定索引和文档的目录
    Directory dir = FSDirectory.open(new File("E:\\dic"));
    //索引和文档的读取对象
    IndexReader indexReader = IndexReader.open(dir);
    //创建索引的搜索对象
    IndexSearcher indexSearcher = new IndexSearcher(indexReader);
    //搜索:第一个参数为查询语句对象, 第二个参数:指定显示多少条
    TopDocs topdocs = indexSearcher.search(query, 5);
    //一共搜索到多少条记录
    System.out.println("=====count=====" + topdocs.totalHits);
    //从搜索结果对象中获取结果集
    ScoreDoc[] scoreDocs = topdocs.scoreDocs;

    for(ScoreDoc scoreDoc : scoreDocs){
        //获取docID
        int docID = scoreDoc.doc;
        //通过文档ID从硬盘中读取出对应的文档
        Document document = indexReader.document(docID);
        //get域名可以取出值 打印
        System.out.println("fileName:" + document.get("fileName"));
        System.out.println("fileSize:" + document.get("fileSize"));
        System.out.println("===================================");
    }
}

@Test
public void testMathAllQuery() throws Exception{
    //创建分词器(创建索引和所有时所用的分词器必须一致)
    Analyzer analyzer = new IKAnalyzer();

    //查询所有文档
    MatchAllDocsQuery query = new MatchAllDocsQuery();

    //指定索引和文档的目录
    Directory dir = FSDirectory.open(new File("E:\\dic"));
    //索引和文档的读取对象
    IndexReader indexReader = IndexReader.open(dir);
    //创建索引的搜索对象
    IndexSearcher indexSearcher = new IndexSearcher(indexReader);
    //搜索:第一个参数为查询语句对象, 第二个参数:指定显示多少条
    TopDocs topdocs = indexSearcher.search(query, 5);
    //一共搜索到多少条记录
    System.out.println("=====count=====" + topdocs.totalHits);
    //从搜索结果对象中获取结果集
    ScoreDoc[] scoreDocs = topdocs.scoreDocs;

    for(ScoreDoc scoreDoc : scoreDocs){
        //获取docID
        int docID = scoreDoc.doc;
        //通过文档ID从硬盘中读取出对应的文档
        Document document = indexReader.document(docID);
        //get域名可以取出值 打印
        System.out.println("fileName:" + document.get("fileName"));
        System.out.println("fileSize:" + document.get("fileSize"));
        System.out.println("======================================");
    }
}

@Test
public void testMultiFieldQueryParser() throws Exception{
    //创建分词器(创建索引和所有时所用的分词器必须一致)
    Analyzer analyzer = new IKAnalyzer();

    String [] fields = {"fileName","fileContext"};
    //从文件名称和文件内容中查询,只有含有apache的就查出来
    MultiFieldQueryParser multiQuery = new MultiFieldQueryParser(fields, analyzer);
    //输入需要搜索的关键字
    Query query = multiQuery.parse("apache");

    //指定索引和文档的目录
    Directory dir = FSDirectory.open(new File("E:\\dic"));
    //索引和文档的读取对象
    IndexReader indexReader = IndexReader.open(dir);
    //创建索引的搜索对象
    IndexSearcher indexSearcher = new IndexSearcher(indexReader);
    //搜索:第一个参数为查询语句对象, 第二个参数:指定显示多少条
    TopDocs topdocs = indexSearcher.search(query, 5);
    //一共搜索到多少条记录
    System.out.println("=====count=====" + topdocs.totalHits);
    //从搜索结果对象中获取结果集
    ScoreDoc[] scoreDocs = topdocs.scoreDocs;

    for(ScoreDoc scoreDoc : scoreDocs){
        //获取docID
        int docID = scoreDoc.doc;
        //通过文档ID从硬盘中读取出对应的文档
        Document document = indexReader.document(docID);
        //get域名可以取出值 打印
        System.out.println("fileName:" + document.get("fileName"));
        System.out.println("fileSize:" + document.get("fileSize"));
        System.out.println("===================================");
    }
}

}

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/100804.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021年7月1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 可以从多个域中进行查询,只有这些域中有关键词的存在就查询出来.
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档