Lucene学习

Lucene搜素引擎的种类垂直搜索,综合搜索
专门搜素和综合性的搜索两种
在Java中采用HttpClient和爬虫技术抓取各个网站的内容

 

2,创建luene的步骤

3,api

 

// 创建索引

    @Test

    publicvoid testCreate() throws Exception{

       //1创建文档对象

       Document document = new Document();

       // 创建并添加字段信息。参数:字段的名称、字段的值、是否存储,这里选Store.YES代表存储到文档列表。Store.NO代表不存储

       document.add(newStringField("id", "1", Store.YES));

       // 这里我们title字段需要用TextField,即创建索引又会被分词。StringField会创建索引,但是不会被分词

       document.add(new TextField("title", "谷歌地图之父跳槽facebook", Store.YES));

      

       //2索引目录类,指定索引在硬盘中的位置

       Directory directory =FSDirectory.open(new File("indexDir"));

       //3创建分词器对象

       Analyzer analyzer = new StandardAnalyzer();

       //4索引写出工具的配置对象

       IndexWriterConfig conf = new IndexWriterConfig(Version.LATEST, analyzer);

       //5创建索引的写出工具类。参数:索引的目录和配置信息

       IndexWriter indexWriter = new IndexWriter(directory, conf);

      

       //6把文档交给IndexWriter

       indexWriter.addDocument(document);

       //7提交

       indexWriter.commit();

       //8关闭

       indexWriter.close();

    }


 

 

 

1.1.1、使用工具查看索引

 

一个Document中可以有很多个不同的字段,每一个字段都是一个Field类的对象。

 

一个Document中的字段其类型是不确定的,因此Field类就提供了各种不同的子类,来对应这些不同类型的字段。


 

问题1:如何确定一个字段是否需要存储?

 

         如果一个字段要显示到最终的结果中,那么一定要存储,否则就不存储

 

问题2:如何确定一个字段是否需要创建索引?

         如果要根据这个字段进行搜索,那么这个字段就必须创建索引。

 

问题3:如何确定一个字段是否需要分词?

         前提是这个字段首先要创建索引。然后如果这个字段的值是不可分割的,那么就不需要分词。例如:ID

 

1.1.1.1、Directory(目录类)

指定索引要存储的位置

        

         FSDirectory:文件系统目录,会把索引库指向本地磁盘。

                   特点:速度略慢,但是比较安全

         RAMDirectory:内存目录,会把索引库保存在内存。

                   特点:速度快,但是不安全

 

 

1.1.1.2、Analyzer(分词器类)

•    提供分词算法,可以把文档中的数据按照算法分词

 

这些分词器,并没有合适的中文分词器,因此一般我们会用第三方提供的分词器:

 

 

 

 

IK分词器官方版本是不支持Lucene4.X的,有人基于IK的源码做了改造,支持了Lucene4.X:

l  基本使用

引入IK分词器:

 

 

l  扩展词典和停用词典

 

 

IK分词器的词库有限,新增加的词条可以通过配置文件添加到IK的词库中,也可以把一些不用的词条去除:

 

 

 

1)  设置配置信息:Lucene的版本和分词器类型

 

2)设置是否清空索引库中的数据

 

1.1.1.1、IndexWriter(索引写出器类)

l  索引写出工具,作用就是实现对索引的增(创建索引)、删(删除索引)、改(修改索引)

 

 

l  可以一次创建一个,也可以批量创建索引

 

查询索引数据

 

 

@Test

 

    publicvoid testSearch() throws Exception {

       // 索引目录对象

       Directory directory =FSDirectory.open(new File("indexDir"));

       // 索引读取工具

       IndexReader reader =DirectoryReader.open(directory);

       // 索引搜索工具

       IndexSearcher searcher = new IndexSearcher(reader);

 

       // 创建查询解析器,两个参数:默认要查询的字段的名称,分词器

       QueryParser parser = new QueryParser("title", newIKAnalyzer());

       // 创建查询对象

       Query query = parser.parse("谷歌地图之父拉斯");

      

       // 搜索数据,两个参数:查询条件对象要查询的最大结果条数

       // 返回的结果是按照匹配度排名得分前N名的文档信息(包含查询到的总条数信息、所有符合条件的文档的编号信息)。

       TopDocs topDocs = searcher.search(query, 10);

       // 获取总条数

       System.out.println("本次搜索共找到" + topDocs.totalHits + "条数据");

       // 获取得分文档对象(ScoreDoc)数组.SocreDoc中包含:文档的编号、文档的得分

       ScoreDoc[] scoreDocs = topDocs.scoreDocs;

       for (ScoreDoc scoreDoc : scoreDocs) {

           // 取出文档编号

           intdocID = scoreDoc.doc;

           // 根据编号去找文档

           Document doc = reader.document(docID);

           System.out.println("id: " + doc.get("id"));

           System.out.println("title: " + doc.get("title"));

           // 取出文档得分

           System.out.println("得分: " + scoreDoc.score);

       }

    }

    /*

     * 测试通配符查询

     * ? 可以代表任意一个字符

     * * 可以任意多个任意字符

     */

    @Test

    publicvoid testWildCardQuery() throws Exception {

       // 创建查询对象

       Query query = new WildcardQuery(new Term("title", "**"));

       search(query);

    }

 

    /*

 

     * 测试普通词条查询

     * 注意:Term(词条)是搜索的最小单位,不可再分词。值必须是字符串!

     */

    @Test

    publicvoid testTermQuery() throws Exception {

       // 创建词条查询对象

       Query query = new TermQuery(newTerm("title", "谷歌地图"));

       search(query);

    }

 

    /*

 

     * 测试模糊查询

     */

    @Test

    publicvoidtestFuzzyQuery() throws Exception {

       // 创建模糊查询对象:允许用户输错。但是要求错误的最大编辑距离不能超过2

       // 编辑距离:一个单词到另一个单词最少要修改的次数facebool -->facebook需要编辑1次,编辑距离就是1

//     Query query = new FuzzyQuery(newTerm("title","fscevool"));

       // 可以手动指定编辑距离,但是参数必须在0~2之间

       Query query = new FuzzyQuery(new Term("title","facevool"),1);

       search(query);

    }


等。。。还有其他的一些查询方式,组合查询,数值范围查询,特殊查询

 

修改索引

 

     * 注意:

     * ALucene修改功能底层会先删除,再把新的文档添加。

     * B:修改功能会根据Term进行匹配,所有匹配到的都会被删除。这样不好

     * C:因此,一般我们修改时,都会根据一个唯一不重复字段进行匹配修改。例如ID

     * D:但是词条搜索,要求ID必须是字符串。如果不是,这个方法就不能用。

* 如果ID是数值类型,我们不能直接去修改。可以先手动删除deleteDocuments(数值范围查询锁定ID),再添加。

 

/ 高亮显示

 

    @Test

    publicvoid testHighlighter() throws Exception {

       // 目录对象

       Directory directory =FSDirectory.open(new File("indexDir"));

       // 创建读取工具

       IndexReader reader =DirectoryReader.open(directory);

       // 创建搜索工具

       IndexSearcher searcher = new IndexSearcher(reader);

 

       QueryParser parser = new QueryParser("title", newIKAnalyzer());

       Query query = parser.parse("谷歌地图");

      

       // 格式化器

       Formatter formatter = new SimpleHTMLFormatter("<em>", "</em>");

       Scorer scorer = new QueryScorer(query);

       // 准备高亮工具

       Highlighter highlighter = new Highlighter(formatter, scorer);

       // 搜索

       TopDocs topDocs = searcher.search(query, 10);

       System.out.println("本次搜索共" + topDocs.totalHits + "条数据");

      

       ScoreDoc[] scoreDocs = topDocs.scoreDocs;

       for (ScoreDoc scoreDoc : scoreDocs) {

           // 获取文档编号

           intdocID = scoreDoc.doc;

           Document doc = reader.document(docID);

           System.out.println("id: " + doc.get("id"));

          

           String title = doc.get("title");

           // 用高亮工具处理普通的查询结果,参数:分词器,要高亮的字段的名称,高亮字段的原始值

           String hTitle = highlighter.getBestFragment(newIKAnalyzer(), "title", title);

          

           System.out.println("title: " + hTitle);

           // 获取文档的得分

           System.out.println("得分:" + scoreDoc.score);

       }

 

    }

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值