官术网_书友最值得收藏!

第2章 自己動(dòng)手寫(xiě)全文檢索

很多軟件系統(tǒng)都需要對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)。信息檢索中最常用的數(shù)據(jù)結(jié)構(gòu)是倒排索引。全文索引如圖2-1所示。

圖2-1 以詞為基礎(chǔ)的全文索引

倒排索引就是一個(gè)詞到文檔列表的映射。用HashMap實(shí)現(xiàn)的一個(gè)簡(jiǎn)單的倒排索引代碼如下。

        public class InvertedIndex {
            Map<String, List<Tuple>> index =
              new HashMap<String, List<Tuple>>(); //詞和這個(gè)詞在文檔中出現(xiàn)的位置信息


            // 索引文檔
            public void indexDoc(String docName, ArrayList<String> words) {
                int pos = 0;
                for (String word : words) {
                    pos++; // 位置
                    List<Tuple> idx = index.get(word);
                    if (idx == null) {
                        idx = new LinkedList<Tuple>();
                        index.put(word, idx);
                    }
                    idx.add(new Tuple(docName, pos));
                    System.out.println("indexed " + docName + " : " + pos + " words");
                }
            }


            // 搜索
            public void search(List<String> words) {
            for (String word : words) {
                Set<String> answer = new HashSet<String>();
                List<Tuple> idx = index.get(word);
                if (idx ! = null) {
                    for (Tuple t : idx) { //找到了一些文檔
                        answer.add(t.docName);
                    }
                }
                System.out.print(word);
                for (String f : answer) {
                    System.out.print(" " + f); //輸出文件名
                }
                System.out.println("");
            }
        }


        private class Tuple { //<文檔名,位置>元組
            private String docName; // 文檔名
            private int position; // 位置


            public Tuple(String d, int position) {
                this.docName = d;
                this.position = position;
            }
        }
    }

如果用戶(hù)的查詢(xún)中包含多個(gè)詞,需要統(tǒng)計(jì)這些詞在文檔中出現(xiàn)的區(qū)間大小。區(qū)間越小的文檔相關(guān)度越高。

        public class Span {
            public int start; // 開(kāi)始位置
            public int end; // 結(jié)束位置


            public Span(int s, int e) {
                start = s;
                end = e;
            }


            public int length() {
                return end - start + 1;
            }


            public String toString() {
                return start + "-" + end;
            }
        }

建立索引往往很耗時(shí),所以應(yīng)把建立好的倒排索引保存到文件。查詢(xún)之前先讀入建立好的索引。

倒排索引由兩個(gè)文件組成:一是文件存儲(chǔ)倒排列表;另外一個(gè)是B樹(shù)(Btree)存儲(chǔ)詞到倒排列表的映射。

索引的實(shí)現(xiàn)接口如下。

        /** 一個(gè)索引應(yīng)該實(shí)現(xiàn)的功能模板 */
        public interface Index {
            /** 使用數(shù)據(jù)庫(kù)統(tǒng)計(jì)類(lèi)構(gòu)建索引 */
            public void build(DatabaseStatistics s);


            /** 從文件加載倒排索引 */
            public void read(String filename) throws IOException;


            /** 把內(nèi)存中建好的倒排索引存入文件 */
            public void flush(String filename) throws IOException;
        }

可以把創(chuàng)建索引和讀入索引的方法分到不同的類(lèi)實(shí)現(xiàn),分別為IndexWriter和IndexReader類(lèi)。

主站蜘蛛池模板: 海淀区| 衡南县| 察雅县| 张北县| 元阳县| 旺苍县| 招远市| 方城县| 荔波县| 郎溪县| 石嘴山市| 平阳县| 明光市| 乌鲁木齐市| 县级市| 滨海县| 永昌县| 天门市| 马边| 雷州市| 陆河县| 黄冈市| 清水县| 南康市| 双江| 龙南县| 武义县| 吉安市| 昌图县| 辉南县| 津南区| 新竹市| 大足县| 灵璧县| 二手房| 榆社县| 元朗区| 桂阳县| 且末县| 济宁市| 武清区|