lucene&solr学习——索引维护

1.索引库的维护

索引库删除

(1) 全删除

第一步:先对文档进行分析

    public IndexWriter getIndexWriter() throws Exception {
//        第一步:创建java工程,并导入jar包
//        第二步:创建一个indexwriter对象(创建索引)
//          1.指定索引库的存放位置Directory对象
        Directory directory = FSDirectory.open(Paths.get("E:\\temp\\index"));  //文件系统目录 file system directory
//        Directory directory2 = new RAMDirectory();
//          2.指定一个分析器,对文档内容进行分析
        Analyzer analyzer = new StandardAnalyzer();//官方推荐分词器
        IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);
        IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);
        return indexWriter;
    }

第二步:直接调用IndexWriter的deleteAll方法

@Test
    public void testAllDelete() throws Exception {
        IndexWriter indexWriter = getIndexWriter();
        indexWriter.deleteAll();
        indexWriter.close();
    }

(2) 根据条件删除

第一步:与上面代码一样

第二步:使用IndexWriter的deleteDocuments方法,传入query条件

@Test
    public void testDelete() throws Exception {
        IndexWriter indexWriter = getIndexWriter();
        Query query = new TermQuery(new Term("fileName", "apache"));
        indexWriter.deleteDocuments(query);
        indexWriter.close();
    }

索引库修改

对索引库的修改,其实就是先删除,在添加。

第一步:同上

第二步:调用IndexWriter的updateDocument方法

//修改
    @Test
    public void testUpdate() throws Exception {
        IndexWriter indexWriter = getIndexWriter();
        Document doc = new Document();
        doc.add(new TextField("fileN", "测试文件名", Store.YES));
        doc.add(new TextField("fileC", "测试文件内容", Store.YES));
        
        indexWriter.updateDocument(new Term("fileName", "spring"), doc);
        indexWriter.close();
    }

索引库查询所有

(1) 使用query的子类查询 (用对象查)

  (1.1) MatchAllDocsQuery

//IndexReader    IndexSearcher
    public IndexSearcher getIndexSearcher() throws Exception {
//        第一步:创建一个Directory对象,也就是索引库存放的位置
        Directory directory = FSDirectory.open(Paths.get("E:\\temp\\index"));
//        第二步:创建一个indexReader对象,需要指定Directory对象
        IndexReader indexReader =DirectoryReader.open(directory);
//        第三步:创建一个indexsearcher对象,需要指定IndexReader对象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);
        return indexSearcher;
    }
    
    //执行查询结果
    public void printResult(IndexSearcher indexSearcher, Query query) throws Exception {
//        第五步:执行查询。
        TopDocs topDocs = indexSearcher.search(query, 10);
//        第六步:返回查询结果,遍历查询结果并输出
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        for (ScoreDoc scoreDoc : scoreDocs) {
            int doc = scoreDoc.doc;
            Document document = indexSearcher.doc(doc);
            //文件名称
            String fileName = document.get("fileName");
            System.out.println(fileName);
            //文件内容
            String fileContent = document.get("fileContent");
            System.out.println(fileContent);
            //文件路径
            String fileSize = document.get("fileSize");
            System.out.println(fileSize);
            //文件大小
            String filePath = document.get("filePath");
            System.out.println(filePath);
            System.out.println("---------");
        }
    }
    //查询所有
    @Test
    public void testMatchAllDocsQuery() throws Exception  {
        IndexSearcher indexSearcher = getIndexSearcher();
        Query query = new MatchAllDocsQuery();
        printResult(indexSearcher, query);
        
        //关闭资源
        indexSearcher.getIndexReader().close();
        
    }

  (1.2) TermQuery 精准查询,之前已经说过。

  (1.3) 根据数值范围查询 (注意:数值范围是否包括边界,使用的方法不一样).

  

//根据数值范围查询
    /*
        版本更新说明:
        在lucene4.10中,关于数字范围的查询是使用的NumericRangerQuery
        使用方式:
        Query query = NumericRangerQuery.newFloatRange(域名,较小值,较大值,是否包含较小值,是否包含较大值)
        在lucene6.6中(不知最早在什么版本,没有细查),NumericRangerQuery被legacyNumericRangerQuery替代
        在lucene7中(应该是从7开始的),lucene开始使用PointValue来替代之前的Filed.而数字范围查询方法也进行了修改,
        Float/Long/IntPoint.newRangeQuery取代了之前的NumericRangeQuery的newFloat/Long/IntRange
        使用方法:
        Query query = Float.newRangeQuery(域名,较小值,较大值);
        而这种查询方法默认包含范围的端点值,即查询的是  较小值<=域名<=较大值
        如果不想包含端点值:
            1.不包含左端点值(即较小值):Query query = Float.newRangeQuery(域名,FloatPoint.nextUp(较小值),较大值);
            2.不包含右端点值(即较大值):Query query = Float.newRangeQuery(域名,较小值,Float.nextDown(较大值));
            3.均不包含:结合1和2即可
     */
    @Test
    public void testNumericRangeQuery() throws Exception  {
        IndexSearcher indexSearcher = getIndexSearcher();
        Query query = LongPoint.newRangeQuery("fileSize", 47L, 200L);
        printResult(indexSearcher, query);
        
        //关闭资源
        indexSearcher.getIndexReader().close();
        
    }

  (1.3) 组合查询条件

  

//可以组合查询条件
    /*
        1、MUST和MUST表示“与”的关系,即“交集”。
        2、MUST和MUST_NOT前者包含后者不包含。
        3、MUST_NOT和MUST_NOT没意义
        4、SHOULD与MUST表示MUST,SHOULD失去意义;
        5、SHOUlD与MUST_NOT相当于MUST与MUST_NOT。
        6、SHOULD与SHOULD表示“或”的概念。
    
       版本更新说明:
       在lucene 4.10.3中,组合查询还有无参构造方法,可以通过下面这种方式实现组合查询:
    
       Query query = new BooleanQuery()
       //添加查询条件,并指定该条件的判断级别
       query.add(query1,Occur.MUST);
       query.add(query2,Occur.MUST);
    
       在lucene7.1中,组合查询只有一个有参构造方法,并没有无参构造方法.而是多了一个静态内部类Builder
    
       public static class Builder {
    
           private int minimumNumberShouldMatch;
           private final List<BooleanClause> clauses = new ArrayList<>();
    
           //大概是4.10.3中的BooleanQuery的无参构造
           public Builder() {}
           //设置最小需要匹配的数
            public Builder setMinimumNumberShouldMatch(int min) {
                this.minimumNumberShouldMatch = min;
                return this;
           }
    
           public Builder add(BooleanClause clause) {
                 if (clauses.size() >= maxClauseCount) {
                    throw new TooManyClauses();
               }
               clauses.add(clause);
               return this;
            }
            //4.10.3中的BooleanQuery的add方法,支持链式编程(一般使用这个add方法)
           public Builder add(Query query, Occur occur) {
               return add(new BooleanClause(query, occur));
           }
           //返回一个BooleanQuery,用于构造Query
           public BooleanQuery build() {
                return new BooleanQuery(minimumNumberShouldMatch, clauses.toArray(new BooleanClause[0]));
           }
       }
    
       7.1中,Occur.MUST等全都放到了BooleanClause中,所以,Occur.MUST等变成了BooleanClause.Occur.MUST等
       所以在lucene中,组合查询的使用方法:
       Query booleanQuery = new BooleanQuery.Builder().add(query1,BooleanClause.Occur.MUST).add(query2,Boolean.Occur.MUST).build();
    */
    public void testBooleanQuery() throws Exception  {
        IndexSearcher indexSearcher = getIndexSearcher();
        Query query1 = new TermQuery(new Term("fileName","lucene"));
        Query query2 = new TermQuery(new Term("fileName","springmvc"));
        //Occur有MUST, SHOULD, MUST_NOT, FILTER
        BooleanQuery booleanQuery = new BooleanQuery.Builder().add(query1, Occur.MUST).add(query2, Occur.SHOULD).build();
        printResult(indexSearcher, booleanQuery);
        
        //关闭资源
        indexSearcher.getIndexReader().close();
        
    }

(2) 使用queryparser查询 (用语法查)

  (2.1) 基础的语法查询,关键词查询:

  域名 + ":" + 搜索的关键字

//条件解析的对象查询
    @Test
    public void testQueryParser() throws Exception  {
        IndexSearcher indexSearcher = getIndexSearcher();
        //参数1,默认查询的域
        QueryParser queryParser = new QueryParser("fileName", new IKAnalyzer());
        // "*:*" : 表示查询所有  "域:值"
        Query query = queryParser.parse("springcloud is springmvc");
        printResult(indexSearcher, query);
        
    }

  (2.2) 范围查询

  域名 + " :" + [最小值 TO 最大值]

  例如:size:[1 TO 100]

  范围查询在lucene中支持数值类型,不支持字符串类型。在solr中支持字符串类型。

  (2.3) 组合条件查询

    (2.3.1) +条件1+条件2:两个条件之间是并且的关系 and

    例如:+fileName:apache + content:apache

    (2.3.2) +条件1 条件2 :必须满足第一个条件,应该满足第二个条件

    例如:+filename:apache content:apache

    (2.3.3)条件1 条件2:两个条件满足其一即可

    例如:filename:apache content:apache

    (2.3.4) -条件1 条件2:必须不满足条件1,要满足条件2

    例如:-filename:apache content:apache

(3) 多个默认检索 MultiFieldQueryParser

//条件解析对象查询  多个默认域
    @Test
    public void testMultiFieldQueryParser() throws Exception  {
        IndexSearcher indexSearcher = getIndexSearcher();
        //参数1,多个默认查询的域
        String[] fields = {"fileName", "fileContent"};
        //参数2,采用分词器
        MultiFieldQueryParser queryParser = new MultiFieldQueryParser(fields, new IKAnalyzer());
        // "*:*" : 表示查询所有  "域:值"
        Query query = queryParser.parse("apache is lucene");
        printResult(indexSearcher, query);
        
    }

 

posted @ 2019-02-18 10:38  MichaelKai  阅读(288)  评论(0编辑  收藏  举报