- 自己動手寫分布式搜索引擎
- 羅剛
- 1114字
- 2020-11-28 15:52:50
3.3.11 使用Collector篩選搜索結果
Collector主要用來從一次查詢中收集原始結果。可以通過它遍歷查詢結果中的每個文檔。執行搜索的Searcher.search()方法可以接收Collector對象作為參數。查詢類每次匹配到一個文檔都會調用Collector對象上的collect(int doc)方法。下面是一個收集文檔,但不對文檔評分的例子:
private static final String FIELD = "contents"; public static void main(String[] args) throws Exception { // 建立使用內存索引的Lucene Directory directory = new RAMDirectory(); Analyzer analyzer = new StandardAnalyzer(); IndexWriterConfig iwc = new IndexWriterConfig(analyzer); IndexWriter writer = new IndexWriter(directory, iwc); // 索引一些文檔 writer.addDocument(createDocument("1", "foo bar baz")); writer.addDocument(createDocument("2", "red green blue")); writer.addDocument(createDocument("3", "The Lucene was made by Doug Cutting")); writer.close(); IndexReader reader = DirectoryReader.open(directory); IndexSearcher searcher = new IndexSearcher(reader); Term t1 = new Term(FIELD, "lucene"); TermQuery query = new TermQuery(t1); final BitSet bits = new BitSet(reader.maxDoc()); searcher.search(query, new Collector() { private int docBase; //忽略評分器 @Override public void setScorer(Scorer scorer) { } //允許文檔亂序 public boolean acceptsDocsOutOfOrder() { return true; } public void collect(int doc) { bits.set(doc + docBase); } public void setNextReader(AtomicReaderContext context) { this.docBase = context.docBase; } }); System.out.println("結果數:" + bits.cardinality()); for (int i = bits.nextSetBit(0); i >= 0; i = bits.nextSetBit(i + 1)) { System.out.println("文檔編號:" + i); } } private static Document createDocument(String id, String content) { Document doc = new Document(); doc.add(new Field("id", id, StringField.TYPE_STORED)); doc.add(new Field(FIELD, content, TextField.TYPE_STORED)); return doc; }
例如,有個Collector的子類TopDocsCollector處理原始的查詢結果,并且返回最相關的N個文檔。
它是一個基類,用于做所有返回TopDocs輸出的類的父類。TopDocsCollector.topDocs()方法返回最相關的N個文檔。
例如:
Query q = ...; IndexSearcher searcher = ...; TopDocsCollector<ScoreDoc> tdc = new MyTopsDocCollector(numResults); searcher.search(q, tdc); //傳遞一個查詢對象和一個Collector對象 //給Searcher.search方法
TopDocsCollector接收一個優先隊列和一個返回結果的總數作為參數。TopScoreDocCollector是TopDocsCollector的子類,也是可以直接使用的類。使用TopScoreDocCollector返回最相關的10個文檔的例子如下:
int hitsPerPage = 10; IndexSearcher searcher = new IndexSearcher(index, true); TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true); searcher.search(q, collector); ScoreDoc[] hits = collector.topDocs().scoreDocs;
一個會員可以發布多條信息,搜索的時候如何將會員發布的信息按每個會員一條的方式顯示。也就是說每個會員編號最多只顯示一條。每個會員最多只顯示和查詢詞最相關的一條信息。這個功能是在結果集而不是在索引庫上遍歷有效文檔,所以應該采用Collector而不是Filter。
可以按指定列排序,然后過濾信息。但是Searcher.search()方法不能同時接收Collector對象和Sort對象。只存在:
searcher.search(query, collector);
對搜索結果首先按會員列排序,然后按相關度排序。找出每個會員最多只顯示和查詢詞最相關的一條信息。讓Collector把這樣的結果放入一個TopDocs對象。
可以擴展TopDocsCollector類。在collect()方法中構造一個新的ScoreDoc對象。
private static final class MyTopsDocCollector extends TopDocsCollector<ScoreDoc> { private int idx = 0; private int base = 0; public MyTopsDocCollector(int size) { super(new HitQueue(size, false)); } @Override protected TopDocs newTopDocs(ScoreDoc[] results, int start) { if (results == null) { return EMPTY_TOPDOCS; } float maxScore = Float.NaN; if (start == 0) { maxScore = results[0].score; } else { for (int i = pq.size(); i > 1; i--) { pq.pop(); } maxScore = pq.pop().score; } return new TopDocs(totalHits, results, maxScore); } @Override public void collect(int doc) throws IOException { ++totalHits; pq.insertWithOverflow(new ScoreDoc(doc + base, scores[idx++])); } @Override public void setNextReader(IndexReader reader, int docBase) throws IOException { base = docBase; } @Override public void setScorer(Scorer scorer) throws IOException { //不做任何事。隨機分配評分值 } @Override public boolean acceptsDocsOutOfOrder() { return true; } }
Collector類的setScorer()方法是一個方法,當IndexSearcher實際執行搜索時,通過IndexSearcher傳入score。
對每個匹配的文檔,調用collect()方法,傳遞一個索引段內部的文檔編號給collect()方法。
會員發布的信息要一輪一輪地顯示,不是說折疊起來就顯示一條。比如會員1有兩條數據:信息1,信息2;會員2也有兩條數據:信息1,信息2,要的結果是會員1的信息1,會員2的信息1,會員1的信息2,會員2的信息2。
把每個會員的相關信息都存到一個優先隊列。所有的搜索結果就是每個會員組成的優先隊列。也就是說,優先隊列有很多。
- Active Directory Disaster Recovery
- PrestaShop 1.3 Theming – Beginner’s Guide
- Vue.js框架與Web前端開發從入門到精通
- User Training for Busy Programmers
- Visio圖形設計從新手到高手(兼容版·第2版)
- 中文版Illustrator CC實用教程
- Authorware應用案例教程
- 攝影照片修飾完全自學手冊
- 中文版Photoshop CS6平面設計實例教程(第2版)
- VRP11/3ds Max虛擬現實制作標準實訓教程
- AutoCAD 2017從新手到高手
- CINEMA 4D R20完全實戰技術手冊
- 音樂日記:Studio One 6場景×風格編曲實用教程
- Photoshop+AE UI動效設計從新手到高手
- 手機/電腦雙平臺剪映短視頻后期編輯從新手到高手