luncene全文搜索引擎(中文分词)

最近在学luncene全文检索。跟着学习视频学的,推荐www.java1234.com上去学下。

关于全文检索:推荐看下全文检索的原理。这里我就不再写了,下面把利用中文分词检索查询的demo给贴出来,以供以后使用。


首先是pom文件


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.luncene.demo</groupId>
  <artifactId>LunceneDemo</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>LunceneDemo Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
   
    <!--  lucnene核心包 -->
    <dependency>
      <groupId>org.apache.lucene</groupId>
      <artifactId>lucene-core</artifactId>
      <version>5.5.0</version>
    </dependency>
    <!-- lucnene解析包 -->
    <dependency>
      <groupId>org.apache.lucene</groupId>
      <artifactId>lucene-queryparser</artifactId>
      <version>5.5.0</version>
    </dependency>
    <!--  lucene 公共包分析器 -->
      <dependency>
          <groupId>org.apache.lucene</groupId>
          <artifactId>lucene-analyzers-common</artifactId>
          <version>5.5.0</version>
      </dependency>
      <!--  中文分词 -->
      <dependency>
          <groupId>org.apache.lucene</groupId>
          <artifactId>lucene-analyzers-smartcn</artifactId>
          <version>5.5.0</version>
      </dependency>
      <!--  关键词高亮显示 -->
      <dependency>
          <groupId>org.apache.lucene</groupId>
          <artifactId>lucene-highlighter</artifactId>
          <version>5.5.0</version>
      </dependency>


      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.12</version>
          <scope>test</scope>
      </dependency>

  </dependencies>
  <build>
    <finalName>LunceneDemo</finalName>
  </build>
</project>


然后是创建索引的类,这里只是根据java1234课程进行了简单的练习,大家如果需要做检索的话, 就会把数据库查询出来的结果信息可以换了。


Indexer.java

package com.java1234.luncene06;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

import java.nio.file.Paths;


/**创建中文索引
 * Created by T430 on 2017/8/2.
 */
public class Indexer {


    private Integer ids[]={1,2,3};
    private String citys[]={"青岛","南京","上海"};
    private String descs[]={
            "青岛是一个美丽的城市",
            "南京是一个文化的城市南京,简称宁,是江苏省会,地处中国东部地区,长江下游,濒江近海。全市下辖11个区,总面积6597平方公里,2013年建成区面积752.83平方公里,常住人口818.78万,其中城镇人口659.1万人。[1-4] “江南佳丽地,金陵帝王州”,南京拥有着6000多年文明史、近2600年建城史和近500年的建都史,是中国四大古都之一,有“六朝古都”、“十朝都会”之称,是中华文明的重要发祥地,历史上曾数次庇佑华夏之正朔,长期是中国南方的政治、经济、文化中心,拥有厚重的文化底蕴和丰富的历史遗存。[5-7] 南京是国家重要的科教中心,自古以来就是一座崇文重教的城市,有“天下文枢”、“东南第一学”的美誉。截至2013年,南京有高等院校75所,其中211高校8所,仅次于北京上海;国家重点实验室25所、国家重点学科169个、两院院士83人,均居中国第三。[8-10] 。\",\n",
            "上海是一个金融城市"
    };

    private Directory dir;//字典


     /**
     * 获取inderWriter示例
     * @return
     * @throws Exception
     */
    private IndexWriter getWriter() throws  Exception{
       // Analyzer analyzer =new StandardAnalyzer();//标准分词器
        //中文分词器
        SmartChineseAnalyzer analyzer= new SmartChineseAnalyzer();
        IndexWriterConfig iwc = new IndexWriterConfig(analyzer);

        IndexWriter writer=new IndexWriter(dir,iwc);//把分的词和字典都写入进去
        return writer;
    }


    /**
     * 构造器
     * @param indexDir 保存的地址
     * @throws Exception
     */
    private void index(String indexDir) throws  Exception{
         dir = FSDirectory.open(Paths.get(indexDir));
        IndexWriter writer = getWriter();

        for (int i = 0; i <ids.length ; i++) {

            Document doc=new Document();//这里选用的是luncene的document,别选错了哦
            /**
             * 这个是把ID加进去,因为ID是int类型的,所以需要用到的是IntField,由于占的空间不大,所以选择YES保存进去
             */
            doc.add(new IntField("id",ids[i], Field.Store.YES));
            /**
             * 这个是把String类型的保存进去,算是标签吧(个人理解),所占空间不大,所以也选择YES保存进去
             */
            doc.add(new StringField("city",citys[i],Field.Store.YES));
            /**
             * 这个是把内容保存进去,大字段的所以选择的是TextField
             */
            doc.add(new TextField("desc",descs[i],Field.Store.YES));
          //添加文档
            writer.addDocument(doc);
        }
        writer.close();//写完以后就要关闭流,保证性能
    }


    public static  void  main(String[] args)  {

        try {
            new Indexer().index("E:\\lucene6");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }







}


下面就开始创建检索的类


package com.java1234.luncene06;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

import java.io.StringReader;
import java.nio.file.Paths;

/**中文分词查询及高亮显示
 * Created by T430 on 2017/8/2.
 */
public class Seracher {

    /**
     * 查询
     * @param indexDir 索引路径
     * @param q 查询用的关键词
     * @throws Exception
     */
    public  static  void  search(String indexDir, String q) throws Exception{

        Directory dir= FSDirectory.open(Paths.get(indexDir));//获取字典内容

        IndexReader reader = DirectoryReader.open(dir);//读出字典

        //索引查询器
        IndexSearcher is= new IndexSearcher(reader);
       // Analyzer analyzer =new StandardAnalyzer();//标准分词器
        SmartChineseAnalyzer analyzer=new SmartChineseAnalyzer();//中文分词器
        //查询解析
        QueryParser parser= new QueryParser("desc",analyzer);
        //格式化查询
        Query query=parser.parse(q);
        //查询前的时间
        long start= System.currentTimeMillis();
        //查询,返回前十的文档
        TopDocs hits=is.search(query,10);
        //查询后的时间
        long end=System.currentTimeMillis();
        System.out.println("匹配:"+q+",中共花费了:"+(end-start
        )+"毫秒");

        QueryScorer scorer= new QueryScorer(query);//片段得分,计算得分,把得分高的片段计算出来
        Fragmenter fragmenter= new SimpleSpanFragmenter(scorer);//把得分放进去,进行格式化
        //设置成html的格式,默认的是粗体, 咱们可以给他改成粗体,红色
        SimpleHTMLFormatter simpleHTMLFormatter= new SimpleHTMLFormatter("<b><font color='red'>","</font></b>");
        Highlighter highlighter=new Highlighter(simpleHTMLFormatter,scorer);//高亮显示片段得分高的部分
        highlighter.setTextFragmenter(fragmenter);//把得分的摘要设置成text显示出来

        //查询到的文档
        for (ScoreDoc scoreDoc: hits.scoreDocs){
            //根据主键ID获取文档
          Document doc= is.doc(scoreDoc.doc);

          System.out.println(doc.get("city"));//输出城市
            String desc=doc.get("desc");//完整的desc数据

            System.out.println(desc);//输出完整的desc
            /**
             * 如果查询得到的desc不为空,则进行高亮,片段显示
             */
            if (desc!=null){
                //获取很多的片段
                TokenStream tokenStream= analyzer.tokenStream("desc",new StringReader(desc));
              String ZhaiYao=  highlighter.getBestFragment(tokenStream,desc);//把权重高的片段摘要显示出来
                System.out.println("显示高亮的关键词片段:===》"+ZhaiYao);
            }
        }
        reader.close();//关闭
    }

    public static  void  main(String[] args) {
        String indexDir = "E:\\lucene6";//索引目录
        String q="南京 厚重";//关键词
        try {
            search(indexDir,q);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


到此为止。 一个简单的中文全文检索就做好了。 对于一般的搜索来说, 完全够用了。 大家可以对这个再进行封装。  就到这了。  




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值