Java技术专题程序员

Lucene 全文检索

2018-10-07  本文已影响14人  爱撒谎的男孩

Lucene 全文检索

Field域

是否分词

是否索引

是否存储

Field的常用类型

Field改进

添加依赖

<!-- 添加lucene支持 -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-core</artifactId>
            <version>4.10.3</version>
        </dependency>

        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-queryparser</artifactId>
            <version>4.10.3</version>
        </dependency>

        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-analyzers-common</artifactId>
            <version>4.10.3</version>
        </dependency>

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>


        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-highlighter</artifactId>
            <version>4.10.3</version>
        </dependency>

        <!-- IK分词器 -->
        <dependency>
            <groupId>com.janeluo</groupId>
            <artifactId>ikanalyzer</artifactId>
            <version>2012_u6</version>
        </dependency>

添加IK中文分词器的扩展

Lucene的工具类

/**
 * Lucene的工具类
 * @author chenjiabing
 */
public class LuceneUtils {
    /**
     * 获取IndexWriter  用于创建索引库
     * @return IndexWriter对象
     * @throws Exception
     */
    public static IndexWriter getIndexWriter() throws Exception{
        //创建索引库存放的位置
        Directory directory=FSDirectory.open(new File("/home/chenjiabing/Documents/Lucene"));
        //使用IK中文分词器
        IKAnalyzer ikAnalyzer=new IKAnalyzer(true);
        
        //创建IndexWriteConfig对象,其中传入的是分析器对象
        IndexWriterConfig indexWriterConfig=new IndexWriterConfig(Version.LATEST, ikAnalyzer);
        
        //创建索引,其中的变量是索引库的位置,索引配置对象
        IndexWriter indexWriter=new IndexWriter(directory, indexWriterConfig);
        return indexWriter;
    }
    
    /**
     * 获取IndexSearcher,用于查询
     * @return IndexSearcher对象
     * @throws Exception
     */
    public static IndexSearcher getIndexSearcher()throws Exception{
        //创建Directory对象,指定索引库的位置
        Directory directory=FSDirectory.open(new File("/home/chenjiabing/Documents/Lucene"));
        //创建IndexReader对象
        IndexReader indexReader=DirectoryReader.open(directory);
        //创建IndexSearcher对象
        IndexSearcher indexSearcher=new IndexSearcher(indexReader);
        return indexSearcher;
    }
    
    /**
     * 根据查询语句,打印结果
     * @param indexSearcher  IndexSearch对象
     * @param query  查询对象
     * @param n  显示结果数量
     * @throws IOException 
     */
    public static void doSearch(IndexSearcher indexSearcher,Query query,Integer n) throws IOException{
        //执行查询
        TopDocs topDocs=indexSearcher.search(query, n);
        
        //返回查询结果
        ScoreDoc[] scoreDocs=topDocs.scoreDocs;
        
        //遍历查询结果
        for (ScoreDoc scoreDoc : scoreDocs) {
            int doc=scoreDoc.doc;  //返回文档的编号
            
            //根据编号查询文档
            Document document=indexSearcher.doc(doc);
            
            //输出文档中定义的域
            System.out.println(document.get("fileName"));
            /*System.out.println(document.get("fileSize"));
            System.out.println(document.get("fileContent"));
            System.out.println(document.get("filePath"));*/
        }
    }
}

创建索引库

// 创建索引
    @Test
    public void testIndex() throws Exception {
        IndexWriter indexWriter=LuceneUtils.getIndexWriter();
        //创建File对象,这里是需要索引的文件
        File file=new File("/home/chenjiabing/Documents/Blog");
        
        //获取文件夹下的所有文件
        File[] files=file.listFiles();
        
        //遍历所有的文件,取出相关 的内容
        for (File f : files) {
            Document document=new Document();  //创建文档对象
            
            //获取文件名
            String fileName=f.getName();
            //创建域  文件名  分词,索引 存储
            Field fieldName=new  TextField("fileName", fileName, Store.YES);
            
            //获取文件大小
            Long fileSize=FileUtils.sizeOf(f);
            //创建文件大小的域,分词,索引,存储
            Field fieldSize=new LongField("fileSize", fileSize, Store.YES);
            
            //获取文件路径
            String filePath=f.getPath();
            //创建文件路径的域 不分词,不索引 但是必须存储,用来找到指定的文件
            Field fieldPath=new StoredField("filePath", filePath);
            
            //获取文件内容
            String fileContent=FileUtils.readFileToString(f);
            
            //创建文件内容的域,分词,索引,存储
            Field fieldContent=new TextField("fileContent", fileContent,Store.YES);
            //将分出的这些域添加到文档中
            document.add(fieldContent);
            document.add(fieldName);
            document.add(fieldPath);
            document.add(fieldSize);
            
            //将文档写入索引库
            indexWriter.addDocument(document);
        }
        //关闭IndexWriter对象
        indexWriter.close();
    }

Query 搜索

TermQuery

     @Test
    public void testTermQuerySearch() throws Exception{
        //获取IndexSearcher
        IndexSearcher indexSearcher=LuceneUtils.getIndexSearcher();
        //创建一个TermQuery对象,指定查询的域和需要查询的词
        TermQuery query=new TermQuery(new Term("fileName","springmvc拦截器"));
        System.out.println(query);
        //打印查询结果
        LuceneUtils.doSearch(indexSearcher, query, 10);
        //关闭IndexReader
        indexSearcher.getIndexReader().close();
    }

NumericRangeQuery

    @Test
    public void testNumericRangeQuery() throws Exception{
        IndexSearcher indexSearcher=LuceneUtils.getIndexSearcher();
        /**
         * 这里是查询文件大小的域:fileSize
         * 第一个参数: 域名
         * 第二个参数:最小值
         * 第三个参数: 最大值
         * 第四个参数: 是否包含最小值
         * 第五个参数: 是否包含最大值
         */
        Query query=NumericRangeQuery.newLongRange("fileSize", 1000L, 2000L, true, true);
        //输出查询条件:fileSize:[1000 TO 2000]
        System.out.println(query);
        LuceneUtils.doSearch(indexSearcher, query, 10);
        //关闭IndexReader
        indexSearcher.getIndexReader().close();
    }

BooleanQuery

 @Test
    public void testBooleanQuery() throws Exception{
        IndexSearcher indexSearcher=LuceneUtils.getIndexSearcher();
        
        //第一个查询条件 根据fileName域查询
        Query query1=new TermQuery(new Term("fileName", "springmvc"));
        //第二个查询条件,根据fileSize查询
        Query query2=NumericRangeQuery.newLongRange("fileSize", 1000L, 2000L, true, true);
        
        //创建BooleanQuery
        BooleanQuery query=new BooleanQuery();
        
        //添加查询条件,这个条件是必须满足的 :Occur.MUST
        query.add(query1,Occur.MUST);
        //添加第二个查询条件,这个条件可满足可不满足,相当于or
        query.add(query2,Occur.SHOULD);
        System.out.println(query);
        //执行查询
        LuceneUtils.doSearch(indexSearcher, query, 10);
        
        indexSearcher.getIndexReader().close();
    }

MatchAllDocsQuery

 //查询所有
    @Test
    public void testMatchAllDoc() throws Exception{
        IndexSearcher indexSearcher=LuceneUtils.getIndexSearcher();
        Query query=new MatchAllDocsQuery();
        System.out.println(query);
        LuceneUtils.doSearch(indexSearcher, query, 10);
        indexSearcher.getIndexReader().close();
    }

QueryParser [常用]

 @Test
    public void testQueryParser() throws Exception{
        IndexSearcher indexSearcher=LuceneUtils.getIndexSearcher();
        /**
         * 第一个参数:指定了默认的查询的域名
         * 第二个参数: 指定了分词器
         */
        QueryParser parser=new QueryParser("fileName",new IKAnalyzer());
        /**
         * 其中的字符串的形式为: *:*
         * 查询所有: *:*
         * 根据默认域名查询直接写一个查询内容即可: "springmvc"
         * 根据指定域名查询: "fileContent:springmvc"
         */
        Query query=parser.parse("fileContent:拦截器");
        System.out.println(query);
        LuceneUtils.doSearch(indexSearcher, query, 50);
        indexSearcher.getIndexReader().close();
    }

MultiFieldQueryParser

  @Test
    public void testMulitFiledQueryParser() throws Exception{
        IndexSearcher indexSearcher=LuceneUtils.getIndexSearcher();
        //指定默认查询的域名
        String[] fields={"fileName","fileContent"};
        
        /**
         * 创建对象
         * 第一个参数: 指定默认域名的数组
         * 第二参数: 指定分词器,这里使用中文分词器
         */
        MultiFieldQueryParser parser=new MultiFieldQueryParser(fields, new IKAnalyzer());
        //这里没有指定域名,因此使用上面指定的两个默认的域名进行查询,这两个默认域名之间是or关系,只要满足就查询返回
        //Query query=parser.parse("springmvc");
        
        //指定filePath域名中搜索
        Query query=parser.parse("filePath:/home/chenjiabing");
        System.out.println(query);
        LuceneUtils.doSearch(indexSearcher, query, 50);
        indexSearcher.getIndexReader().close();
    }
    

索引维护

添加索引

删除索引

指定条件删除

@Test
public void deleteIndex() throws Exception {
    // 创建分词器,标准分词器
    Analyzer analyzer = new IKAnalyzer();

    // 创建IndexWriter
    IndexWriterConfig cfg = new IndexWriterConfig(Version.LUCENE_4_10_3,
            analyzer);
    Directory directory = FSDirectory
            .open(new File("E:\\11-index\\hcx\\"));
    // 创建IndexWriter
    IndexWriter writer = new IndexWriter(directory, cfg);

    // Terms
    writer.deleteDocuments(new Term("id", "1"));

    writer.close();
}

删除全部

// 删除索引
@Test
public void deleteIndex() throws Exception {
    // 1、指定索引库目录
    Directory directory = FSDirectory.open(new File("E:\\11-index\\0720"));
    // 2、创建IndexWriterConfig
    IndexWriterConfig cfg = new IndexWriterConfig(Version.LATEST,
            new StandardAnalyzer());
    // 3、 创建IndexWriter
    IndexWriter writer = new IndexWriter(directory, cfg);
    // 4、通过IndexWriter来删除索引
    // a)、删除全部索引
    writer.deleteAll();
    // 5、关闭IndexWriter
    writer.close();
}

修改索引

@Test
public void updateIndex() throws Exception {
    // 创建分词器,标准分词器
    Analyzer analyzer = new StandardAnalyzer();

    // 创建IndexWriter
    IndexWriterConfig cfg = new IndexWriterConfig(Version.LUCENE_4_10_3,
            analyzer);

    Directory directory = FSDirectory
            .open(new File("E:\\11-index\\hcx\\"));
    // 创建IndexWriter
    IndexWriter writer = new IndexWriter(directory, cfg);

    // 第一个参数:指定查询条件
    // 第二个参数:修改之后的对象
    // 修改时如果根据查询条件,可以查询出结果,则将以前的删掉,然后覆盖新的Document对象,如果没有查询出结果,则新增一个Document
    // 修改流程即:先查询,再删除,在添加
    Document doc = new Document();
    doc.add(new TextField("name", "lisi", Store.YES));
    writer.updateDocument(new Term("name", "zhangsan"), doc);

    writer.close();
}
上一篇下一篇

猜你喜欢

热点阅读