且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Lucene就是这么简单(二)

更新时间:2022-10-13 20:12:51

创建索引库的步骤:

  • 1)创建JavaBean对象
  • 2)创建Docment对象
  • 3)将JavaBean对象所有的属性值,均放到Document对象中去,属性名可以和JavaBean相同或不同
  • 4)创建IndexWriter对象
  • 5)将Document对象通过IndexWriter对象写入索引库中
  • 6)关闭IndexWriter对象


@Test
    public void createIndexDB() throws Exception {
        //把数据填充到JavaBean对象中
        User user = new User("1", "钟福成", "未来的程序员");
        //创建Document对象【导入的是Lucene包下的Document对象】
        Document document = new Document();
        //将JavaBean对象所有的属性值,均放到Document对象中去,属性名可以和JavaBean相同或不同
        /**
         * 向Document对象加入一个字段
         * 参数一:字段的关键字
         * 参数二:字符的值
         * 参数三:是否要存储到原始记录表中
         *      YES表示是
         *      NO表示否
         * 参数四:是否需要将存储的数据拆分到词汇表中
         *      ANALYZED表示拆分
         *      NOT_ANALYZED表示不拆分
         *
         * */
        document.add(new Field("id", user.getId(), Field.Store.YES, Field.Index.ANALYZED));
        document.add(new Field("userName", user.getUserName(), Field.Store.YES, Field.Index.ANALYZED));
        document.add(new Field("sal", user.getSal(), Field.Store.YES, Field.Index.ANALYZED));
        //创建IndexWriter对象
        //目录指定为E:/createIndexDB
        Directory directory = FSDirectory.open(new File("E:/createIndexDB"));
        //使用标准的分词算法对原始记录表进行拆分
        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);
        //LIMITED默认是1W个
        IndexWriter.MaxFieldLength maxFieldLength = IndexWriter.MaxFieldLength.LIMITED;
        /**
         * IndexWriter将我们的document对象写到硬盘中
         *
         * 参数一:Directory d,写到硬盘中的目录路径是什么
         * 参数二:Analyzer a, 以何种算法来对document中的原始记录表数据进行拆分成词汇表
         * 参数三:MaxFieldLength mfl 最多将文本拆分出多少个词汇
         *
         * */
        IndexWriter indexWriter = new IndexWriter(directory, analyzer, maxFieldLength);
        //将Document对象通过IndexWriter对象写入索引库中
        indexWriter.addDocument(document);
        //关闭IndexWriter对象
        indexWriter.close();
    }

Lucene就是这么简单(二)这里写图片描述

程序执行完,我们就会在硬盘中见到我们的索引库。

Lucene就是这么简单(二)这里写图片描述


那我们现在是不知道记录是否真真正正存储到索引库中的,因为我们看不见。索引库存放的数据放在cfs文件下,我们也是不能打开cfs文件的

于是,我们现在用一个关键字,把索引库的数据读取。看看读取数据是否成功。

根据关键字查询索引库中的内容:

  • 1)创建IndexSearcher对象
  • 2)创建QueryParser对象
  • 3)创建Query对象来封装关键字
  • 4)用IndexSearcher对象去索引库中查询符合条件的前100条记录,不足100条记录的以实际为准
  • 5)获取符合条件的编号
  • 6)用indexSearcher对象去索引库中查询编号对应的Document对象
  • 7)将Document对象中的所有属性取出,再封装回JavaBean对象中去,并加入到集合中保存,以备将之用


@Test
    public void findIndexDB() throws Exception {
        /**
         * 参数一: IndexSearcher(Directory path)查询以xxx目录的索引库
         *
         * */
        Directory directory = FSDirectory.open(new File("E:/createIndexDB"));
        //创建IndexSearcher对象
        IndexSearcher indexSearcher = new IndexSearcher(directory);
        //创建QueryParser对象
        /**
         * 参数一: Version matchVersion 版本号【和上面是一样的】
         * 参数二:String f,【要查询的字段】
         * 参数三:Analyzer a【使用的拆词算法】
         * */
        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);
        QueryParser queryParser = new QueryParser(Version.LUCENE_30, "userName", analyzer);
        //给出要查询的关键字
        String keyWords = "钟";
        //创建Query对象来封装关键字
        Query query = queryParser.parse(keyWords);
        //用IndexSearcher对象去索引库中查询符合条件的前100条记录,不足100条记录的以实际为准
        TopDocs topDocs = indexSearcher.search(query, 100);
        //获取符合条件的编号
        for (int i = 0; i < topDocs.scoreDocs.length; i++) {
            ScoreDoc scoreDoc = topDocs.scoreDocs[i];
            int no = scoreDoc.doc;
            //用indexSearcher对象去索引库中查询编号对应的Document对象
            Document document = indexSearcher.doc(no);
            //将Document对象中的所有属性取出,再封装回JavaBean对象中去
            String id = document.get("id");
            String userName = document.get("userName");
            String sal = document.get("sal");
            User user = new User(id, userName, sal);
            System.out.println(user);
        }

Lucene就是这么简单(二)这里写图片描述

效果:

Lucene就是这么简单(二)这里写图片描述



1.3进一步说明Lucene代码


我们的Lucene程序就是大概这么一个思路:将JavaBean对象封装到Document对象中,然后通过IndexWriter把document写入到索引库中。当用户需要查询的时候,就使用IndexSearcher从索引库中读取数据,找到对应的Document对象,从而解析里边的内容,再封装到JavaBean对象中让我们使用

Lucene就是这么简单(二)这里写图片描述


二、对Lucene代码优化


我们再次看回我们上一篇快速入门写过的代码,我来截取一些有代表性的:

以下代码在把数据填充到索引库,和从索引库查询数据的时候,都出现了。是重复代码

Directory directory = FSDirectory.open(new File("E:/createIndexDB"));
        //使用标准的分词算法对原始记录表进行拆分
        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);

以下的代码其实就是将JavaBean的数据封装到Document对象中,我们是可以通过反射来对其进行封装….如果不封装的话,我们如果有很多JavaBean都要添加到Document对象中,就会出现很多类似的代码。

document.add(new Field("id", user.getId(), Field.Store.YES, Field.Index.ANALYZED));
        document.add(new Field("userName", user.getUserName(), Field.Store.YES, Field.Index.ANALYZED));
        document.add(new Field("sal", user.getSal(), Field.Store.YES, Field.Index.ANALYZED));

以下代码就是从Document对象中把数据取出来,封装到JavaBean去。如果JavaBean中有很多属性,也是需要我们写很多次类似代码….

//将Document对象中的所有属性取出,再封装回JavaBean对象中去
            String id = document.get("id");
            String userName = document.get("userName");
            String sal = document.get("sal");
             User user = new User(id, userName, sal);