• 分享一些关于Lucene的心得


    Lucene的概述

    Lucene是一个全文搜索框架,而不是应用产品。因此它并不像http://www.baidu.com/ 或者google Desktop那么拿来就能用,它只是提供了一种工具让你能实现这些产品。

    lucene能做什么

     lucene的功能很单一,说到底,就是你给它若干个字符串,然后它为你提供一个全文搜索服务,告诉你你要搜索的关键词出现在哪里。知道了这个本质,你就可以发挥想象做任何符合这个条件的事情了。你可以把站内新闻都索引了,做个资料库;你可以把一个数据库表的若干个字段索引起来,那就不用再担心因为“%like%”而锁表了;你也可以写个自己的搜索引擎……

    2 lucene的工作方式

    lucene提供的服务实际包含两部分:一入一出。所谓入是写入,即将你提供的源(本质是字符串)写入索引或者将其从索引中删除;所谓出是读出,即向用户提供全文搜索服务,让用户可以通过关键词定位源。

    写入流程

    1.源字符串首先经过analyzer处理,包括:分词,分成一个个单词;去除stopword(可选)。

    2.将源中需要的信息加入Document的各个Field中,并把需要索引的Field索引起来,把需要存储的Field存储起来。

    3.将索引写入存储器,存储器可以是内存或磁盘。

    主要关键字【作用】

    a) Analysis:分词器

    Analysis包含一些内建的分析器,例如按空白字符分词的WhitespaceAnalyzer,添加了stopwrod过滤的StopAnalyzer,最常用的StandardAnalyzer。

    b) Documet:文档

    就是我们的源数据的封装结构,我们需要把源数据分成不同的域,放入到documet里面,到时搜索时也可以指定搜索哪些域(Field)了。

    c) Directory : 目录,这是对目录的一个抽象,这个目录可以是文件系统上面的一个dir(FSDirectory),也可以是内存的一块(RAMDirectory),MmapDirectory为使用内存映射的索引。

    放在内存的话就会避免IO的操作耗时了,根据需要选择就是了。

    d) IndexWriter : 索引书写器,也就是维护器,对索引进行读取和删除操作的类

    e) IndexReader : 索引读取器,用于读取指定目录的索引。

    f) IndexSearcher : 索引的搜索器,就是把用户输入拿到索引列表中搜索的一个类

    需要注意的是,这个搜索出来的就是(TopDocs)索引号,还不是真正的文章。

    g) Query : 查询语句,我们需要把我们的查询String封装成Query才可以交给Searcher来搜索 ,查询的最小单元是Term,Lucene的Query有很多种,根据不同的需求选用不同的Query就是了.

    i. TermQuery:

    如果你想执行一个这样的查询:“在content域中包含‘lucene’的document”,那么你可以用TermQuery:

    Term t = new Term( " content " , " lucene " ); Query query = new TermQuery(t);

    ii. BooleanQuery:多个query的【与或】关系的查询

    如果你想这么查询:“在content域中包含java或perl的document”,那么你可以建立两个TermQuery并把它们用BooleanQuery连接起来:

    TermQuery termQuery1 = new TermQuery( new Term( " content " , " java " ); TermQuery termQuery 2 = new TermQuery( new Term( " content " , " perl " ); BooleanQuery booleanQuery = new BooleanQuery(); booleanQuery.add(termQuery1, BooleanClause.Occur.SHOULD); booleanQuery.add(termQuery2, BooleanClause.Occur.SHOULD);

    iii. WildcardQuery : 通配符的查询

    如果你想对某单词进行通配符查询,你可以用WildcardQuery,通配符包括’?’匹配一个任意字符和’*’匹配零个或多个任意字符,例如你搜索’use*’,你可能找到’useful’或者’useless’:

    Query query = new WildcardQuery(new Term("content", "use*");

    iv. PhraseQuery : 在指定的文字距离内出现的词的查询

    你可能对中日关系比较感兴趣,想查找‘中’和‘日’挨得比较近(5个字的距离内)的文章,超过这个距离的不予考虑,你可以:

    PhraseQuery query = new PhraseQuery();

    query.setSlop(5);

    query.add(new Term("content ", “中”));

    query.add(new Term(“content”, “日”));

    那么它可能搜到“中日合作……”、“中方和日方……”,但是搜不到“中国某高层领导说日本欠扁”。

    v. PrefixQuery : 查询词语是以某字符开头的

    如果你想搜以‘中’开头的词语,你可以用PrefixQuery:

    PrefixQuery query = new PrefixQuery(new Term("content ", "中");

    vi. FuzzyQuery : 相似的搜索

    FuzzyQuery用来搜索相似的term,使用Levenshtein算法。假设你想搜索跟‘wuzza’相似的词语,你可以:

    Query query = new FuzzyQuery(new Term("content", "wuzza");

    你可能得到‘fuzzy’和‘wuzzy’。

    vii. TermRangeQuery : 范围内搜索

    你也许想搜索时间域从20060101到20060130之间的document,你可以用TermRangeQuery:

    TermRangeQuery query2 = TermRangeQuery.newStringRange("time", "20060101", "20060130", true, true);

    最后的true表示用闭合区间。

    viii.

    h) TopDocs :结果集,就是searcher搜索的结果,里面就是一些ScoreDoc,这个对象的doc成员就是这个Id了!

    要想得到文章,那么就得需要用这个Id去取文章了,searcher提供了用id得到document的方法,于是就取到了数据了

        //庖丁分析器
            Analyzer analyzer = new PaodingAnalyzer();
                List<Article> resu = docRecordService.wx(0);//取元数据
                //创建Directory
                Directory dir = FSDirectory.open(new File(indexDir));
                //创建Writer
                IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_44, analyzer);
                iwc.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);//设置索引维护的方式
                IndexWriter writer = new IndexWriter(dir, iwc);
                try {
                    for (int i = 0; i < resu.size(); i++) {
                            //文档实体类
                            DocRecord drec = new DocRecord();
                            //创建文档
                            Document document = new Document();
                            drec.setFileName(resu.get(i).getPid());
                            drec.setDocType("weixin");
                            drec.setLastModify(System.currentTimeMillis());
                            drec.setTitle(resu.get(i).getTitle());
                            try {
                                System.out.println("开始分词工作 : ------>   " + i);
                                long time = resu.get(i).getPublishTimeMillis();
                                if((time+"").length()<11){
                                    time = time*1000;
                                }
                                String tag = resu.get(i).getArticleTag();
                                //得到时间戳
                                dateTime = resu.get(i).getPublishTimeMillis();
                                FieldType testType = new FieldType();
                                testType.setIndexed(false);
                                testType.setTokenized(false);
                                testType.setStored(true);
                                //创建文章    标题,标签,简介,分类,时间,封面图地址,原文地址
                                document.add(new StringField("fileName", resu.get(i).getPid(), Field.Store.YES));
                                document.add(new TextField("abstracts", resu.get(i).getAbstracts()==null?"":resu.get(i).getAbstracts(), Field.Store.YES));
                                if(null!=resu.get(i).getPublisher() && !"".equals(resu.get(i).getPublisher())){
                                    document.add(new StringField("author", resu.get(i).getPublisher(), Field.Store.YES));
                                }else{
                                    document.add(new StringField("author", resu.get(i).getAuthor(), Field.Store.YES));
                                }
                                document.add(new StringField("categoryCode", resu.get(i).getCategoryCode(), Field.Store.YES));
                                document.add(new StringField("categoryName", resu.get(i).getCategoryName()==null?"":resu.get(i).getCategoryName(), Field.Store.YES));
                                document.add(new Field("imageUrl", resu.get(i).getThemeImageUrls(), testType));
                                document.add(new Field("sourceUrl", resu.get(i).getSourceUrl(), testType));
                                document.add(new StringField("isCopyRight", resu.get(i).getIsCopyRight(), Field.Store.YES));
                                document.add(new StringField("source", resu.get(i).getSource(), Field.Store.YES));
                                document.add(new TextField("title", resu.get(i).getTitle(), Field.Store.YES));
                                document.add(new LongField("date",time , Field.Store.YES));   //这里的yes表示可以建立索引搜索
                                if(null!=resu.get(i).getSn() && !"".equals(resu.get(i).getSn())){
                                    document.add(new StringField("sn",resu.get(i).getSn() , Field.Store.YES));
                                }
                                if(null!=tag && !"".equals(tag)){
                                    document.add(new StringField("tag", tag, Field.Store.YES));
                                }
                                
                                writer.updateDocument(new Term("fileName",(resu.get(i).getPid())!=null?(resu.get(i).getPid()):""), document);
                                //更新数据库is_index字段,说明数据已做索引
    //                            int id = docRecordService.createDoc(drec);
                                System.out.println("完成分词工作 : ------>   " + i);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    
                    writer.close();
                    dir.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
  • 相关阅读:
    2.六角星绘制
    1.五角星绘制
    Redis
    javaScript
    反射
    区分'方法'和'函数'
    递归,二分法
    匿名函数,排序函数,过滤函数,映射函数,
    生成器,生成器函数,推导式,生成器表达式.
    函数,闭包,迭代器
  • 原文地址:https://www.cnblogs.com/buglove/p/5667128.html
Copyright © 2020-2023  润新知