zoukankan      html  css  js  c++  java
  • lucene 学习之编码篇

    本文环境:lucene5.2     JDK1.7   IKAnalyzer

    引入lucene相关包

    <!-- lucene核心包 -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-core</artifactId>
            <version>5.2.0</version>
        </dependency>
          <!-- 查询解析器 -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-queryparser</artifactId>
            <version>5.2.0</version>
        </dependency>
          <!-- 分词器 -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-analyzers-common</artifactId>
            <version>5.2.0</version>
        </dependency>

    开发中依赖的包

    <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
        
        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>

    一、创建索引


    1、确定索引库的位置

    a、将索引库存入本地磁盘

    FSDirectory dir=FSDirectory.open(path);

    b、将索引存入内存

    Directory directory = new RAMDirectory();

    2、创建分词器

    //创建分词器
            Analyzer al=new StandardAnalyzer();

         lucene内置有四个分析器:WhitespaceAnalyzer、SimpleAnalyzer、StopAnalyser、StandardAnalyzer

    • WhitespaceAnalyzer:分析器是通过空格来分割文本信息
    • SimpleAnalyzer:分析器会首先通过非字母字符来拆分文本信息,并统一转为小写格式,会去掉数字类型的字符
    • StopAnalyser:和SimpleAnalyzer分析器类似,但StopAnalyser会去掉一些常用单词(the、a、an..)
    • StandardAnalyzer:是lucene最复杂的核心分析器,可以识别某些种类的语汇单元,如公司名称、Email、主机名称等,它会将语汇单元转为小写格式,并去除掉停用词和标点符号

    3、创建IndexWriter,进行索引文件的写入。

    //创建索引的写入配置对象
            IndexWriterConfig iwc= new IndexWriterConfig(al);
            //创建索引的Writer
            IndexWriter iw=new IndexWriter(dir, iwc);

    4、创建文档 创建域将内容提取并进行索引的存储

    //创建文档
                Document doc=new Document();
                //创建域 (域是键值对的数据结构)Store.YES:将该值存储到索引库
                Field fieldName=new TextField("fieldName","xs.txt",Store.YES);
                Field fieldContent=new TextField("fieldContent","san guo yan yi",Store.YES);
                Field fieldsize=new LongField("fieldSize",10324,Store.YES);
                Field fieldPath=new TextField("fieldPath","F:/xs/sg/xs.txt",Store.YES);
                //将域加入文档中
                doc.add(fieldName);
                doc.add(fieldContent);
                doc.add(fieldsize);
                doc.add(fieldPath);
                //把文档写入索引库
                iw.addDocument(doc);

    Field域的3各重要属性:

     a、是否分析

       将field值按照指定的分词器进行分析出相应的语汇单元,将词进行索引。例如:博文标题、博文作者、博文描述、博文内容 ,这些都应该建立索引

     b、是否索引

      对field分析后的词或整个field值进行索引,只有建立索引的field才能被搜索

     c、是否存储(Store.YES:表示存储   Store.NO:表示不存储)

      将field值存储在文档中,只有存储在文档中的field才可以从Document中取出。(一般对于内容较大的field不建立存储)

    常用Field域的类型:

    5、提交,并关闭资源

    //提交
            iw.commit();
            iw.close();

    完整代码:

     1 @Test
     2     public void ImportIndex() throws IOException {
     3         //获得索引库路径
     4         Path path=Paths.get("E:\test\luceneWI");
     5         //打开索引库
     6         FSDirectory dir=FSDirectory.open(path);
     7         //创建分词器
     8         Analyzer al=new StandardAnalyzer();
     9         //创建索引的写入配置对象
    10         IndexWriterConfig iwc= new IndexWriterConfig(al);
    11         //创建索引的Writer
    12         IndexWriter iw=new IndexWriter(dir, iwc);
    13         //采集原始文档
    14         File sourceFile=new File("E:\test\lucene");
    15         //获取该文件下所有的文件
    16         File [] files=sourceFile.listFiles();
    17         //遍历每一个文件
    18         for(File file:files){
    19             //获取文件属性
    20             String fileName=file.getName();
    21             String content=FileUtils.readFileToString(file);
    22             long size=FileUtils.sizeOf(file);
    23             String sourcePath=file.getPath();
    24             //创建文档
    25             Document doc=new Document();
    26             //创建域 (域是键值对的数据结构)Store.YES:将该值存储到索引库
    27             Field fieldName=new TextField("fieldName",fileName,Store.YES);
    28             Field fieldContent=new TextField("fieldContent",content,Store.YES);
    29             Field fieldsize=new LongField("fieldSize",size,Store.YES);
    30             Field fieldPath=new TextField("fieldPath",sourcePath,Store.NO);
    31             //将域加入文档中
    32             doc.add(fieldName);
    33             doc.add(fieldContent);
    34             doc.add(fieldsize);
    35             doc.add(fieldPath);
    36             //把文档写入索引库
    37             iw.addDocument(doc);
    38         }
    39         //提交
    40         iw.commit();
    41         iw.close();
    42     }
    View Code

    执行结果查看索引库

     我们使用 luke可以查看索引库的具体信息luke-5.3.0-luke-release

    二、添加索引

    添加前我们的索引库中有7各文档

    现在我们要新加一条文档

    @Test
        public void addIndex() throws IOException {
            //获得索引库路径
            Path path=Paths.get("E:\test\luceneWI");
            //打开索引库
            FSDirectory dir=FSDirectory.open(path);
            //创建分词器
            Analyzer al=new IKAnalyzer();
            //创建索引的写入配置对象
            IndexWriterConfig iwc= new IndexWriterConfig(al);
            //创建索引的Writer
            IndexWriter iw=new IndexWriter(dir, iwc);
            //新建一个文件 china.txt
            File file=new File("E:\test\lucene\china.txt");
            String fileName=file.getName();
            String content=FileUtils.readFileToString(file);
            long size=FileUtils.sizeOf(file);
            String sourcePath=file.getPath();
            //创建域 (域时键值对的数据结构)Store.YES:在索引库中是否以存储的形式存在
            Field fieldName=new TextField("fieldName",fileName,Store.YES);
            Field fieldContent=new TextField("fieldContent",content,Store.YES);
            Field fieldsize=new LongField("fieldSize",size,Store.YES);
            Field fieldPath=new TextField("fieldPath",sourcePath,Store.YES);
            //创建文档
            Document doc=new Document();
            //将域加入文档中
            doc.add(fieldName);
            doc.add(fieldContent);
            doc.add(fieldPath);
            doc.add(fieldsize);
            //把文档写入索引库
            iw.addDocument(doc);
            iw.commit();
            iw.close();
        }

    执行后

    三、删除索引

    1、删除所有

    @Test
        public void deleteIndexAll() throws IOException {
            //获得索引库路径
            Path path=Paths.get("E:\test\luceneWI");
            //打开索引库
            FSDirectory dir=FSDirectory.open(path);
            //创建分词器
            Analyzer al=new IKAnalyzer();
            //创建索引的写入配置对象
            IndexWriterConfig iwc= new IndexWriterConfig(al);
            //创建索引的Writer
            IndexWriter iw=new IndexWriter(dir, iwc);
            iw.deleteAll();//删除所有
            iw.commit();//提交
            iw.close();//关闭资源
        }

    2、按照条件删除

    @Test
        public void deleteIndexAllQuery() throws IOException {
            //获得索引库路径
            Path path=Paths.get("E:\test\luceneWI");
            //打开索引库
            FSDirectory dir=FSDirectory.open(path);
            //创建分词器
            Analyzer al=new IKAnalyzer();
            //创建索引的写入配置对象
            IndexWriterConfig iwc= new IndexWriterConfig(al);
            //创建索引的Writer
            IndexWriter iw=new IndexWriter(dir, iwc);
            //创建语汇单元
            Term term=new Term("fieldName","china");// 要删除的document中包含的语汇单元
            //创建根据语汇单元的查询对象
            Query query=new TermQuery(term);
            iw.deleteDocuments(query);
            iw.commit();//提交
            iw.close();//关闭资源
        }

    四、查询

    1、分词语汇单元查询

    @Test
        public void QueryIndexAll() throws IOException {
            //获得索引库路径
            Path path=Paths.get("E:\test\luceneWI");
            //打开索引库
            FSDirectory dir=FSDirectory.open(path);
            //创建索引库的读取对象
            DirectoryReader reader=DirectoryReader.open(dir);
            //创建索引库的搜索对象
            IndexSearcher is=new IndexSearcher(reader);
            //创建语汇单元
            Term term=new Term("fieldName","license");// 要删除的document中包含的语汇单元
            //创建根据语汇单元的查询对象
            TermQuery tq=new TermQuery(term);
            TopDocs result=is.search(tq, 10);//查询前10条
            int totalHits=result.totalHits;//获取总记录数
            System.out.println("totalHits:"+totalHits);
            //获取文档列表
            ScoreDoc[] sd=result.scoreDocs;
            for(ScoreDoc sc:sd){
                int id=sc.doc;//获取文档ID
                Document doc=is.doc(id);//获取文档
                String fieldName=doc.get("fieldName");
                String fieldContent=doc.get("fieldContent");
                String fieldSize=doc.get("fieldSize");
                String fieldPath=doc.get("fieldPath");
                System.out.println("fieldName:"+fieldName);
                System.out.println("fieldContent:"+fieldContent);
                System.out.println("fieldSize:"+fieldSize);
                System.out.println("fieldPath:"+fieldPath);
            }
        }

     2、数值范围查询

    @Test
        public void queryIndexNumberAll() throws IOException {
            //获得索引库路径
            Path path=Paths.get("E:\test\luceneWI");
            //打开索引库
            FSDirectory dir=FSDirectory.open(path);
            //创建索引库的读取对象
            DirectoryReader reader=DirectoryReader.open(dir);
            //创建索引库的搜索对象
            IndexSearcher is=new IndexSearcher(reader);
            //创建数值查询对象
            Query tq=NumericRangeQuery.newLongRange("fieldSize", 0L, 100L, true, true);
            System.out.println("打印查询对象:"+tq);//打印查询对象:fieldSize:[0 TO 100]
            TopDocs result=is.search(tq, 10);//查询前10条
            int totalHits=result.totalHits;//获取总记录数
            System.out.println("totalHits:"+totalHits);
            //获取文档列表
            ScoreDoc[] sd=result.scoreDocs;
            for(ScoreDoc sc:sd){
                int id=sc.doc;//获取文档ID
                Document doc=is.doc(id);//获取文档
                String fieldName=doc.get("fieldName");
                String fieldContent=doc.get("fieldContent");
                String fieldSize=doc.get("fieldSize");
                String fieldPath=doc.get("fieldPath");
                System.out.println("fieldName:"+fieldName);
                System.out.println("fieldContent:"+fieldContent);
                System.out.println("fieldSize:"+fieldSize);
                System.out.println("fieldPath:"+fieldPath);
            }
        }

    3、多查询对象联合查询

        @Test
        public void bqqueryIndexNumberAll() throws IOException {
            //获得索引库路径
            Path path=Paths.get("E:\test\luceneWI");
            //打开索引库
            FSDirectory dir=FSDirectory.open(path);
            //创建索引库的读取对象
            DirectoryReader reader=DirectoryReader.open(dir);
            //创建索引库的搜索对象
            IndexSearcher is=new IndexSearcher(reader);
            //创建多条件查询对象,通过控制& 或者| 或者 ! 来组合查询条件
            BooleanQuery tq=new BooleanQuery();
            //创建分词语汇查询对象
            Query query1=new TermQuery(new Term("fieldName","china"));
            Query query2=new TermQuery(new Term("fieldContent","china"));
            Query query3=NumericRangeQuery.newLongRange("fieldSize", 0L, 100L, true, true);
            //通过BooleanQuery 控制 两个查询条件的关系
            tq.add(query1,Occur.MUST);
            tq.add(query2,Occur.MUST); //Occur.MUST 同时满足  Occur.SHOULD: 可以满足可以不满足 Occur.MUST_NOT:不能满足
            tq.add(query3,Occur.MUST);
             System.out.println("bq:"+tq);//bq:+fieldName:china +fieldContent:china ( 表示 必须同时满足两个条件)
            TopDocs result=is.search(tq, 10);//查询前10条
            int totalHits=result.totalHits;//获取总记录数
            System.out.println("totalHits:"+totalHits);
            //获取文档列表
            ScoreDoc[] sd=result.scoreDocs;
            for(ScoreDoc sc:sd){
                int id=sc.doc;//获取文档ID
                Document doc=is.doc(id);//获取文档
                String fieldName=doc.get("fieldName");
                String fieldContent=doc.get("fieldContent");
                String fieldSize=doc.get("fieldSize");
                String fieldPath=doc.get("fieldPath");
                System.out.println("fieldName:"+fieldName);
                System.out.println("fieldContent:"+fieldContent);
                System.out.println("fieldSize:"+fieldSize);
                System.out.println("fieldPath:"+fieldPath);
            }
        }

    4、解析查询

    QueryParser 对查询条件进行分词查询
        @Test
        public void queryParserIndexAll() throws  Exception {
            //获得索引库路径
            Path path=Paths.get("E:\test\luceneWI");
            //打开索引库
            FSDirectory dir=FSDirectory.open(path);
            //创建索引库的读取对象
            DirectoryReader reader=DirectoryReader.open(dir);
            //创建索引库的搜索对象
            IndexSearcher is=new IndexSearcher(reader);
            //创建查询解析对象
            QueryParser qp=new QueryParser("fieldName", new IKAnalyzer());//分词器要与创建索引的一样
            //通过QueryParser解析查询对象
            Query tq=qp.parse("爱我china");//单个查询条件
        //    Query tq=qp.parse("fieldName:爱我   OR fieldContent:china");//多个查询条件  OR /AND
             System.out.println("tq:"+tq);//tq:fieldName:爱我 fieldName:我 fieldName:china (进行分词了)
            TopDocs result=is.search(tq, 10);//查询前10条
            int totalHits=result.totalHits;//获取总记录数
            System.out.println("totalHits:"+totalHits);
            //获取文档列表
            ScoreDoc[] sd=result.scoreDocs;
            for(ScoreDoc sc:sd){
                int id=sc.doc;//获取文档ID
                Document doc=is.doc(id);//获取文档
                String fieldName=doc.get("fieldName");
                String fieldContent=doc.get("fieldContent");
                String fieldSize=doc.get("fieldSize");
                String fieldPath=doc.get("fieldPath");
                System.out.println("fieldName:"+fieldName);
                System.out.println("fieldContent:"+fieldContent);
                System.out.println("fieldSize:"+fieldSize);
                System.out.println("fieldPath:"+fieldPath);
            }
        }

    5、多域解析查询

    @Test
        public void queryManyParserIndexAll() throws  Exception {
            //获得索引库路径
            Path path=Paths.get("E:\test\luceneWI");
            //打开索引库
            FSDirectory dir=FSDirectory.open(path);
            //创建索引库的读取对象
            DirectoryReader reader=DirectoryReader.open(dir);
            //创建索引库的搜索对象
            IndexSearcher is=new IndexSearcher(reader);
            //定义多个域
            String [] fields={"fieldName","fieldContent"};
            //创建查询解析对象  查询的语汇单词之间的关系是或,只要满足其中一个语汇单元,就可以查询出来
            MultiFieldQueryParser mp=new MultiFieldQueryParser(fields, new IKAnalyzer());
            Query tq=mp.parse("爱我china");
             System.out.println("tq:"+tq);//tq:(fieldName:爱我 fieldName:我 fieldName:china) (fieldContent:爱我 fieldContent:我 fieldContent:china)
            TopDocs result=is.search(tq, 10);//查询前10条
            int totalHits=result.totalHits;//获取总记录数
            System.out.println("totalHits:"+totalHits);
            //获取文档列表
            ScoreDoc[] sd=result.scoreDocs;
            for(ScoreDoc sc:sd){
                int id=sc.doc;//获取文档ID
                Document doc=is.doc(id);//获取文档
                String fieldName=doc.get("fieldName");
                String fieldContent=doc.get("fieldContent");
                String fieldSize=doc.get("fieldSize");
                String fieldPath=doc.get("fieldPath");
                System.out.println("fieldName:"+fieldName);
                System.out.println("fieldContent:"+fieldContent);
                System.out.println("fieldSize:"+fieldSize);
                System.out.println("fieldPath:"+fieldPath);
            }
        }
  • 相关阅读:
    html JS 打开本地程序及文件
    [转]jquery mobile中redirect重定向问题
    kafka中broker、producer、consumer主要配置参数说明
    手写一个LruCache
    ES发布时max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144] 错误
    UML类图
    JVM调优总结
    JVM学习系列(五) 常见的JVM参数
    JVM学习系列(四) 相关概念
    JVM学习系列(三) 虚拟机监控相关
  • 原文地址:https://www.cnblogs.com/jalja/p/6611469.html
Copyright © 2011-2022 走看看