龙陵县 祁门县 雅安市 崇左市 宝坻区 红原县 龙南县 鄄城县 义马市 凤庆县 林甸县 邵东县 余庆县 隆尧县 临猗县 望谟县

文章导航软件下载安卓资源苹果资源

pc软件新闻网络操作系统办公服务器软件评测

安卓新闻资讯安卓游戏攻略综合安卓评测

苹果ios资讯苹果手机越狱美化教程ios软件教程mac教程

单机游戏即时战略动作射击棋牌游戏体育竞技模拟经营其它游戏游戏工具

网游cf活动lol周免英雄lol礼包

手游最新动态手游评测手游活动手游问答

您的位置:角色扮演 → 怪物猎人世界新装备介绍 怪物猎人世界新装备新系统一览

越狱第四季_Lucene 源码分析之倒排索引(二)

标签:血循环 在线中国象棋网络版

本文以及后面几篇文章将讲解如何定位 Lucene 中的倒排索引。内容很多,唯有静下心才能跟着思路遨游。

我们可以思考一下,哪个步骤与倒排索引有关,很容易想到检索文档一定是要查询倒排列表的,那么就从此处入手。检索文档通过调用 IndexSearcher.search(Query query, int n) 方法返回匹配的文档。

public class IndexSearcher {
    public TopDocs search(Query query, int n) throws IOException {
        return searchAfter(null, query, n);
    }

    public TopDocs searchAfter(ScoreDoc after, Query query, int numHits) throws IOException {
        // ...
        return search(query, manager);
    }

    public <C extends Collector, T> T search(Query query, CollectorManager<C, T> collectorManager) throws IOException {
        if (executor == null) {
            final C collector = collectorManager.newCollector();
            search(query, collector);
            return collectorManager.reduce(Collections.singletonList(collector));
        }
        // ...
    }
}

上面是 search 的调用链,最终调用的核心方法是 reduce(...),也就是说 reduce(...) 会返回匹配的文档。

下文通过聚焦 reduce(...) 方法定位 Lucene 中的倒排索引。

reduce(...) 方法的形参是 Collections.singletonList(collector),collector 是由 CollectorManager.newCollector() 方法创建的,而 CollectorManager 创建于上面代码中第二个方法 searchAfter 方法中的匿名内部类,代码如下。

public class IndexSearcher {
    public TopDocs searchAfter(ScoreDoc after, Query query, int numHits) throws IOException {
        // ...
        final CollectorManager<TopScoreDocCollector, TopDocs> manager = new CollectorManager<TopScoreDocCollector, TopDocs>() {
            @Override
            public TopScoreDocCollector newCollector() throws IOException {
                return TopScoreDocCollector.create(cappedNumHits, after);
            }
            // ...
        };
        // ...
    }
}

public abstract class TopScoreDocCollector extends TopDocsCollector<ScoreDoc> {
    public static TopScoreDocCollector create(int numHits, ScoreDoc after) {
        return new SimpleTopScoreDocCollector(numHits);
    }
}

也就是说 reduce 的形参是一个集合,该集合包含一个 SimpleTopScoreDocCollector 对象。

回到 reduce 的内部实现,调用方也是 searchAfter 方法中的匿名内部类 CollectorManager,代码如下。

public class IndexSearcher {
    public 琅琊榜_2018年最新新闻网TopDocs searchAfter(ScoreDoc after, Query query, int numHits) throws IOException {
        // ...
        final CollectorManager<TopScoreDocCollector, TopDocs> manager = new CollectorManager<TopScoreDocCollector, TopDocs>() {
            // ...
            @Override
            public TopDocs reduce(Collection<TopScoreDocCollector> collectors) throws IOException {
                final TopDocs[] topDocs = new TopDocs[collectors.size()];
                int i = 0;
                for (TopScoreDocCollector collector : collectors) {
                    topDocs[i++] = collector.topDocs();
                }
                return TopDocs.merge(0, cappedNumHits, topDocs, true);
            }

        };
        // ...
    }
}

由于 reduce(...) 方法的形参仅有一个元素,reduce(...) 方法退化成执行 SimpleTopScoreDocCollector.topDocs(),其结果就是匹配的文档。

public abstract class TopScoreDocCollector extends TopDocsCollector<ScoreDoc> {
    private static class SimpleTopScoreDocCollector extends TopScoreDocCollector {
        // ...
    }
}

public abstract class TopDocsCollector<T extends ScoreDoc> implements Collector {
    public TopDocs topDocs() {
        return topDocs(0, topDocsSize());
    }

    public TopDocs topDocs(int start, int howMany) {
        // ...
        ScoreDoc[] results = new ScoreDoc[howMany];
        // ...
        populateResults(results, howMany);
        return newTopDocs(results, start);
    }

    protected void populateResults(ScoreDoc[] results, int howMany) {
        for (int i = howMany - 1; i >= 0; i--) { 
            results[i] = pq.pop();
        }
    }
}

SimpleTopScoreDocCollector 继承自 TopScoreDocCollector 继承自 TopDocsCollector,实际执行 TopDocsCollector.topDocs()。

时刻记住 reduce() 返回匹配的文档,也就是说 TopDocsCollector. topDocs() 返回匹配的文档。 results 作为 NewTopDocs 的成员变量一定包含了匹配的文档,results 又来自于 pq.pop(),那么 pq 一定包含了匹配的文档。

下面通过聚焦 SimpleTopScoreDocCollector 对象的 pq 定位倒排索引。

回顾 CollectorManager.reduce(...) 所在的 search(...) 方法,在初始化 SimpleTopScoreDocCollector 和 reduce(...) 之间唯一的方法就是另一个 search(…) 方法,一定是在这个方法中赋值了 pq,代码如下。

public class IndexSearcher {
    public void search(Query query, Collector results) throws IOException {
        search(leafContexts, createNormalizedWeight(query, results.needsScores()), results);
    }

    protected void search(List<LeafReaderContext> leaves, Weight weight, Collector co爱上超模_2018年最新新闻网llector) throws IOException {
        for (LeafReaderContext ctx : leaves) { // search each subreader
            final LeafCollector leafCollecto一拳超人_2018年最新新闻网r = collector.getLeafCollector(ctx);
            BulkScorer scorer = weight.bulkScorer(ctx);
            scorer.score(leafCollector, ctx.reader().getLiveDocs());
        }
    }
}

一共就三个方法,究竟是在哪个方法中赋值了 pq 呢?一个个分析。

第一个方法,collector.getLeafCollector(ctx) 实际调用的就是 SimpleTopScoreDocCollector.getLeafCollector(ctx)。

public abstract class TopScoreDocCollector extends TopDocsCollector<ScoreDoc> {
    private static class SimpleTopScoreDocCollector extends TopScoreDocCollector {
        @Override
        public LeafCollector getLeafCollector(LeafReaderContext context) throws IOException {
            final int docBase = context.docBase;
            return new ScorerLeafCollector() {
                @Ove佞_2018年最新新闻网rride
                public void collect(int doc) throws IOException {
                    float score = scorer.score();
                    totalHits++;               
                    pqTop.doc = doc + docBase;
                    pqTop.score = score;
                    pqTop = pq.updateTop();
                }
            };
        }
    }
}

可以看到 getLeafCollector(...) 方法返回的 ScorerLeafCollector 类提供了 collect(doc) 方法对 pq 进行操作。也就是说找到调用 collect(doc) 方法的地方也就找到了倒排索引。

下面通过聚焦找到调用 collect() 方法的来源来定位倒排索引。

第二个方法,weight.bulkScorer(ctx) 创建 BulkScorer,而 weight 由 createNormalizedWeight(…) 创建。

public class IndexSearcher {
    public Weight createNormalizedWeight(Query query, boolean needsScores) throws IOException {
        // ...
        return createWeight(query, needsScores, 1f);
    }

    public Weight createWeight(Query query, boolean needsScores, float boost) throws IOException {
        // ...
        Weight weight = query.createWeight(this, needsScores, boost);
        // ...
        return weight;
    }
}

假设 query 是最简单的 TermQuery,createWeight(…) 代码如下。

public class TermQuery extends Query {
    @Override
    public Weight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
        // ...
        return new TermWeight(searcher, needsScores, boost, termState);
    }
}

最终返回的是 TermWeight 对象,那么 weight.bulkScorer(ctx) 实现类代码如下。

public abstract class Weight implements SegmentCacheable {
    public BulkScorer bulkScorer(LeafReaderContext context) throws IOException {        
        // ...
        return new DefaultBulkScorer(scorer);
    }
}

最终返回的是一个 DefaultBulkScorer 对象。

第三个方法,scorer.score(…),实际调用类是 DefaultBulkScorer,代码如下。

public abstract class Weight implements SegmentCach哈姆雷特_2018年最新新闻网eable {
    protected static class DefaultBulkScorer extends BulkScorer {
        // ...
    }
}

public abstract class BulkScorer {
    public void score(LeafCollector collector, Bits acceptDocs) throws IOException {
        final int next = score(collector, acceptDocs, 0, DocIdSetIterator.NO_MORE_DOCS);
    }
}

BulkScorer.score(…) 内部调用的还是 DefaultBulkScorer 中重构的 score(…) 方法,代码如下。

public abstract class Weight implements SegmentCacheable {
    protected static class DefaultBulkScorer extends BulkScorer {
        @Override
        public int score(LeafCollector collector, Bits accep郭德纲祭拜恩师_2018年最新新闻网tDocs, int min, int max) throws IOException {
            collector.setScorer(scorer);
            if (scorer.docID() == -1 && min == 0 && max == DocIdSetIterator.NO_MORE_DOCS) {
                scoreAll(collector, iterator, twoPhase, acceptDocs);
                return DocIdSetIterator.NO_MORE_DOCS;
            }
        }

        static void scoreAll(LeafCollector collector, DocIdSetIterator iterator, TwoPhaseIterator twoPhase, Bits acceptDocs) throws IOException {
            if (twoPhase == null) {
                for (int doc = iterator.nextDoc(); doc != DocIdSetIterator.NO_MORE_DOCS; doc = iterator.nextDoc()) {
                    if (acceptDocs == null || acceptDocs.get(doc)) {
                        collector.collect(doc);
                    }
                }
            }
        }
    }
}

看到了什么!找到了调用 collect(…) 方法的代码。

当前文章:http://www-dexinxi-com.h6thgon.tw/xnqtk/a22f3_151979.html

发布时间:2019-07-20 03:01:12

银河娱乐手机官网  919银河优越会  澳门银河2949所有网址  澳门银河官网手机app  919银河优越会千斤小龙虾翻车 遭过往车辆碾压成  澳门银河娱乐yh163am.com  澳门银河官网真人娱乐  澳门银河真人yh163am.com  银河优越会下载  银河娱乐在线官方网址  

相关阅读 EA旗下游戏《FIFA 18》预测世界杯法国将夺冠新华网批腾讯:多少道文件才能管住网游对少年儿童的戕害?ThreadPoolExecutor源码解析(二)腾讯直播 | “东坡奖”水电施工技能大赛 宜春站颁奖典礼小米8现货吗?雷军:正在拼命生产!《四驱兄弟》新漫画:小豪霸气爆发 大神儿子洗白

文章评论
发表评论

热门文章 象山打造三治结合乡村治理新样本每天7件!蚂蚁金服专利申请量四年即将破万数据与媒体未来——数据传播行之深圳1元抵50元,出门问问智能单耳耳机 TicPod Solo京东250元预约

最新文章 HMD将于5月29日在莫斯科举办发布会:或为诺基亚X6海外版马化腾:中兴事件,把中国科技业打醒了 17岁大学生发现重大安全漏洞,谷歌奖励3.6万美元开鲁县50万亩红干椒大田移栽全面展开“偷拍上司通奸”民警涉罪被采取刑事强制措施 涉事副局长被查

人气排行 VOSS矿泉水,生活需要精致和奢华动漫星空晚报:《食戟之灵》学园新秩序大小姐威严坐镇 《名侦探柯南》票房突破75亿日元特斯拉发布刹车更新包:制动距离可缩短约6米天猫精灵销量突破300万台:国内排名第一美国休斯顿一座化工厂爆炸22人受伤 系阀门损坏所致