SlideShare a Scribd company logo
100行ぐらいで書く分散検索エンジ
            ン
      Hadoop + Lucene

            太田一樹
    <kzk@il.is.s.u-tokyo.ac.jp>
自己紹介
• 太田一樹
 – http://kzk9.net/
 – 東京大学情報理工学系研究科コンピューター
   科学専攻石川研究室
今回のテーマ
• Javaで分散検索エンジンを楽をして作る
 – Lucene (検索エンジン)
 – Hadoop (MapReduceフレームワーク)


• 個人でも大規模な検索エンジンがさくっ
  と作れる時代ということを示してみる
Agenda
•   Luceneの説明
•   Hadoopの説明
•   Lucene + Hadoopで検索エンジンを構築
•   まとめ
(Lucene)とは?
• Javaで書かれた検索エンジン
 – Yahoo ResearchのDougCutting氏が開発
 – Javaのクラスライブラリとして提供され、他
   のソフトウェアから簡単に使用可能
 – 文章サイズにもよるが、数百万件程度なら1
   台で検索可能

• 検索できるようになるまでの流れ
 – 文章を登録し、検索用インデックスを作成
 – 検索用インデックスを読み込み、クエリーを
   発行
Luceneインデックス作成サンプ
                 ル
  //インデックスに登録するファイルのあるディレクトリ
 File directory = new File(args[0]);
 String[] filepath = directory.list();
 //インデックスの保存先
 String index = args[1];
 //インデクサの生成
 IndexWriter writer = new IndexWriter(index, new JapaneseAnalyzer(), true);
 //文書の解析
 for (int i = 0; i < filepath.length; i++) {
             Document doc = new Document();
             //ファイルの登録
             doc.add(Field.UnIndexed(quot;urlquot;, filepath[i]));
             Reader reader = new FileReader(filepath[i]);
             //文書内容の登録
             doc.add(Field.Text(quot;contentsquot;,reader));
             writer.addDocument(doc);
 }
 //インデクサのクローズ
 writer.optimize(); writer.close();
Luceneインデックス作成サンプ
                 ル
  //インデックスに登録するファイルのあるディレクトリ
 File directory = new File(args[0]);
 String[] filepath = directory.list();
 //インデックスの保存先
 String index = args[1];
 //インデクサの生成
 IndexWriter writer = new IndexWriter(index, new JapaneseAnalyzer(), true);
 //文書の解析
 for (int i = 0; i < filepath.length; i++) {
             Document doc = new Document();
             //ファイルの登録
             doc.add(Field.UnIndexed(quot;urlquot;, filepath[i]));
             Reader reader = new FileReader(filepath[i]);
             //文書内容の登録
             doc.add(Field.Text(quot;contentsquot;,reader));
             writer.addDocument(doc);
 }
 //インデクサのクローズ
 writer.optimize(); writer.close();
Luceneインデックス作成サンプ
                 ル
  //インデックスに登録するファイルのあるディレクトリ
 File directory = new File(args[0]);
 String[] filepath = directory.list();
 //インデックスの保存先
 String index = args[1];
 //インデクサの生成
 IndexWriter writer = new IndexWriter(index, new JapaneseAnalyzer(), true);
 //文書の解析
 for (int i = 0; i < filepath.length; i++) {
             Document doc = new Document();
             //ファイルの登録
             doc.add(Field.UnIndexed(quot;urlquot;, filepath[i]));
             Reader reader = new FileReader(filepath[i]);
             //文書内容の登録
             doc.add(Field.Text(quot;contentsquot;,reader));
             writer.addDocument(doc);
 }
 //インデクサのクローズ
 writer.optimize(); writer.close();
Luceneインデックス作成サンプ
                 ル
  //インデックスに登録するファイルのあるディレクトリ
 File directory = new File(args[0]);
 String[] filepath = directory.list();
 //インデックスの保存先
 String index = args[1];
 //インデクサの生成
 IndexWriter writer = new IndexWriter(index, new JapaneseAnalyzer(), true);
 //文書の解析
 for (int i = 0; i < filepath.length; i++) {
             Document doc = new Document();
             //ファイルの登録
             doc.add(Field.UnIndexed(quot;urlquot;, filepath[i]));
             Reader reader = new FileReader(filepath[i]);
             //文書内容の登録
             doc.add(Field.Text(quot;contentsquot;,reader));
             writer.addDocument(doc);
 }
 //インデクサのクローズ
 writer.optimize(); writer.close();
Lucene検索サンプル

// インデックス読み込み
IndexSearcher is = new IndexSearcher(quot;indexquot;);
// クエリーパーサーの作成
QueryParser qp = new QueryParser(quot;contentquot;, new SimpleAnalyzer());
// 検索クエリーの準備
Query q = qp.parse(“SomeQueryquot;);
// 検索を実行
Hits hs = is.search(q);
// 検索結果を表示
System.out.println(hs.length() + quot; hit(s)quot;);
for(int i=0; i<hs.length(); i++) {
            System.out.println(hs.doc(i).toString());
}
is.close();
Hadoopとは?
• Googleの基盤ソフトウェアのクローン
  – Google File System
  – MapReduce
• Yahoo Research の Doug Cutting氏が開発
  – 元々はNutch Crawlerのサブプロジェクト
  – Dougの子供の持っているぬいぐるみの名前
• Javaで記述
Hadoop参考文献
• Hadoop公式サイト
 – http://hadoop.apache.org/core/
 – Wiki: http://wiki.apache.org/hadoop/
    • インストール方法・チュートリアル・プレゼン資
      料など
• Hadoop解析資料 (拙著)
 • http://preferred.jp/pub/hadoop.html
• Hadoop, hBaseで構築する大規模データ処
  理システム on CodeZine (拙著)
 – http://codezine.jp/a/article/aid/2448.aspx
MapReduceの実行フロー


          Map
Data

                          Reduce   Data

                Shuffle
          Map
Data

                          Reduce   Data

          Map
Data
Hadoopのスケーラビリティ
• Scaling 4000 nodes at Yahoo!
  – http://developer.yahoo.net/blogs/hadoop/2008/09/sc
    aling_hadoop_to_4000_nodes_a.html
• Hadoop wins Terabyte Sort Benchmark
  – http://developer.yahoo.net/blogs/hadoop/2008/07/a
    pache_hadoop_wins_terabyte_sort_benchmark.html


• Hadoopで書いとけば、4000ノードぐらいま
  ではスケールするよ!
例: ワードカウント
入力文書: doc1

 foo foo foo
 bar bar buzz




                 Map
    Data

                                 Reduce   Data

                       Shuffle
                 Map
    Data

                                 Reduce   Data

                 Map
    Data
例: ワードカウント
入力文書: doc1

 foo foo foo
 bar bar buz




                     Map
    Data
        doc1: foo
                                     Reduce   Data
        doc1: foo

                           Shuffle
                     Map
    Data
        doc1: foo
                                     Reduce
        doc1: bar                             Data

                     Map
    Data
        doc1: bar
        doc1: buz
例: ワードカウント
入力文書: doc1

 foo foo foo
 bar bar buz


               doc1: foo
               doc1: foo
                           Map
    Data

                                           Reduce   Data
               doc1: foo
               doc1: bar
                                 Shuffle
                           Map
    Data

                                           Reduce
               doc1: bar                            Data
               doc1: buz
                           Map
    Data
例: ワードカウント
入力文書: doc1

 foo foo foo
 bar bar buz


               doc1: foo         foo: 1
               doc1: foo         foo: 1
                           Map
    Data

                                          Reduce   Data
               doc1: foo         bar: 1
               doc1: bar         foo: 1
                           Map
    Data

                                          Reduce
               doc1: bar         bar: 1            Data
               doc1: buz         buz: 1
                           Map
    Data
例: ワードカウント
入力文書: doc1

 foo foo foo
 bar bar buz


                foo: 1
                foo: 1
                         bar: <1, 1>
                Map
    Data
                         buz: <1>
                                       Reduce   Data
                bar: 1
                foo: 1
                Map
    Data                 foo: <1, 1, 1>

                                       Reduce
                bar: 1                          Data
                buz: 1
                Map
    Data
例: ワードカウント
入力文書: doc1

 foo foo foo
 bar bar buz




                      bar: <1, 1>
                Map
    Data
                      buz: <1>
                                    Reduce   Data

                Map
    Data              foo: <1, 1, 1>

                                    Reduce   Data

                Map
    Data
例: ワードカウント
入力文書: doc1

 foo foo foo
 bar bar buz




                      bar: <1, 1>            bar: 2
                Map
    Data
                      buz: <1>               buz: 1
                                    Reduce            Data

                Map
    Data              foo: <1, 1, 1>         foo: 3

                                    Reduce            Data

                Map
    Data
例: ワードカウント
入力文書: doc1

 foo foo foo
 bar bar buz




                               bar: 2
                Map
    Data
                               buz: 1
                      Reduce   Data

                Map
    Data                       foo: 3

                      Reduce   Data

                Map
    Data
作成する検索エンジンの仕組み
                              検索用ノード
                               Lucene
クロールしてきた文章
                              インデック
                                 ス1
                               Lucene
 url1: <html>…
                              インデック
 url2: <html>…
                                 ス2
 url3: <html>…
                               Lucene
                  Hadoopによる
 url4: <html>…                           分散
                              インデック
                 分散インデックス
 url5: <html>…                          クエリー
                                 ス3
                      作成
 url6: <html>…                           発行
                               Lucene
 url7: <html>…
                              インデック
        …                        ス4
                               Lucene
                              インデック
                                 ス5
Hadoopによる分散インデックス作
             成


url1: <html>…
                Map
      Data
url2: <html>…

                                Reduce   Data

url3: <html>…
                      Shuffle
                Map
      Data
url4: <html>…

                                Reduce   Data

url5: <html>…
                Map
      Data
url6: <html>…
Hadoopによる分散インデックス作
          成


       url1: <html>…
            Map
Data   url2: <html>…
                                 Reduce   Data

       url3: <html>…
                       Shuffle
            Map
Data   url4: <html>…

                                 Reduce   Data

       url5: <html>…
            Map
Data   url6: <html>…
Hadoopによる分散インデックス作
          成


       url1: <html>…
            Map
Data   url2: <html>…
                                 url1: <html>…
                                 url4: <html>…
                                    Reduce       Data
                                 url5: <html>…
       url3: <html>…
                       Shuffle
            Map
Data   url4: <html>…
                                 url2: <html>…
                                    Reduce
                                 url3: <html>…   Data
                                 url6: <html>…
       url5: <html>…
            Map
Data   url6: <html>…
Hadoopによる分散インデックス作
          成

              url1: <html>…    Lucene
              url4: <html>…   インデック
       Map
Data          url5: <html>…      ス

                         Reduce           Data

              url2: <html>…      Lucene
             Shuffle<html>…
       Map
Data          url3:            インデック
              url6: <html>…        ス
                          Reduce          Data

       Map
Data
Hadoopによる分散インデックス作
          成

                        Lucene
                       インデック
       Map
Data                      ス

                        Reduce   Data

                        Lucene
             Shuffle
       Map
Data                   インデック
                          ス
                        Reduce   Data

       Map
Data
Hadoopによる分散インデックス作
          成

                        Lucene
                       インデック
       Map
Data                      ス

                        Reduce   Data
                        Lucene
                       インデック
             Shuffle
       Map
Data
                          ス
                        Reduce   Data

       Map
Data
Hadoopによる分散インデックス作
          成


                                 Lucene
       Map
Data                            インデック
                                   ス
                       Reduce     Data

                                 Lucene
             Shuffle
       Map
Data                            インデック
                                   ス
                       Reduce     Data

       Map
Data
分散インデックス作成
  (Mapフェーズ)


 // 何もしない
 public void map(Text key, Text value,
           OutputCollector<Text, Text> output,
           Reporter reporter) throws IOException {
    Text url = key;
    Text str = value;
    output.collect(url, str);
 }
分散インデックス作成
                (Reduceフェーズ)

public void reduce(Text key, Iterator<Text> values,
            OutputCollector<Text, Writable> output,
            Reporter reporter) throws IOException {
  // URL
  Text url = key;
  // 本文
  Text str = values.next();
  // ドキュメントを追加
  Document doc = new Document();
  doc.add(new Field(quot;urlquot;, url.toString(), Field.Store.YES, Field.Index.NO));
  doc.add(new Field(quot;contentquot;, str.toString(), Field.Store.YES, Field.Index.TOKENIZED));
  output.collect(url, new LuceneDocumentWrapper(doc));
}
分散インデックス作成
       (Reduce終了フェーズ)
public void close(final Reporter reporter) throws IOException {
       // 分散ファイルシステムに保存するための何か
       final Path perm = new Path(job.getOutputPath(), name);
       final Path temp = job.getLocalPath(
           “index/_” + Integer.toString(new Random().nextInt()));
       // インデックス作成
       final IndexWriter writer = new IndexWriter(
           fs.startLocalOutput(perm, temp).toString(),
           new JapaneseAnalyzer(), true);
       try {
                writer.optimize();
                writer.close();
                fs.completeLocalOutput(perm, temp); // copy to dfs
       } finally {
                closed = true;
       }
}
以上のコードを実行
• Hadoopのインストール
 – 今回は24 (dual core)台のクラスタを使用
• ビルド
• 実行
 – bin/hadoop jar indexer.ja net.kzk9.indexer in out
• 分散ファイルシステムのoutというディレ
  クトリにLuceneインデックスが作成されて
  いる
 – 30Gのドキュメントで約2-3時間?
作成する検索エンジンの仕組み
                              検索用ノード
                               Lucene
クロールしてきた文章
                              インデック
                 ここを作った
                                 ス1
                               Lucene
 url1: <html>…
                              インデック
 url2: <html>…
                                 ス2
 url3: <html>…
                               Lucene
                  Hadoopによる
 url4: <html>…                           分散
                              インデック
                 分散インデックス
 url5: <html>…                          クエリー
                                 ス3
                      作成
 url6: <html>…                           発行
                               Lucene
 url7: <html>…
                              インデック
        …                        ス4
                               Lucene
                              インデック
                                 ス5
落ち穂拾い
• 時間的にここまで
• 残りのタスク
 – クエリー受け付け用のサーバーを用意
 – 作成されたインデックスをそいつらに転送
 – クライアントから各サーバーにクエリーを発
   行
とはいえ
• 商用検索エンジンにするには絶対的に欠
  けている要素
 – ランキング
 – クローラー
• OSSの分散検索エンジン
 – Nutch
   • OSSの検索エンジン
   • あんまり出来が良くない
 – Senna
   • 分散バージョンマダー?
まとめ
• Luceneの使い方を説明
• Hadoopの使い方を説明
• 組み合わせて分散でインデックスを作成
  する方法を紹介
おわり

% wc -l indexer.java
145 indexer.java

More Related Content

Hadoop @ Java CCC 2008 Spring

  • 2. 自己紹介 • 太田一樹 – http://kzk9.net/ – 東京大学情報理工学系研究科コンピューター 科学専攻石川研究室
  • 3. 今回のテーマ • Javaで分散検索エンジンを楽をして作る – Lucene (検索エンジン) – Hadoop (MapReduceフレームワーク) • 個人でも大規模な検索エンジンがさくっ と作れる時代ということを示してみる
  • 4. Agenda • Luceneの説明 • Hadoopの説明 • Lucene + Hadoopで検索エンジンを構築 • まとめ
  • 5. (Lucene)とは? • Javaで書かれた検索エンジン – Yahoo ResearchのDougCutting氏が開発 – Javaのクラスライブラリとして提供され、他 のソフトウェアから簡単に使用可能 – 文章サイズにもよるが、数百万件程度なら1 台で検索可能 • 検索できるようになるまでの流れ – 文章を登録し、検索用インデックスを作成 – 検索用インデックスを読み込み、クエリーを 発行
  • 6. Luceneインデックス作成サンプ ル //インデックスに登録するファイルのあるディレクトリ File directory = new File(args[0]); String[] filepath = directory.list(); //インデックスの保存先 String index = args[1]; //インデクサの生成 IndexWriter writer = new IndexWriter(index, new JapaneseAnalyzer(), true); //文書の解析 for (int i = 0; i < filepath.length; i++) { Document doc = new Document(); //ファイルの登録 doc.add(Field.UnIndexed(quot;urlquot;, filepath[i])); Reader reader = new FileReader(filepath[i]); //文書内容の登録 doc.add(Field.Text(quot;contentsquot;,reader)); writer.addDocument(doc); } //インデクサのクローズ writer.optimize(); writer.close();
  • 7. Luceneインデックス作成サンプ ル //インデックスに登録するファイルのあるディレクトリ File directory = new File(args[0]); String[] filepath = directory.list(); //インデックスの保存先 String index = args[1]; //インデクサの生成 IndexWriter writer = new IndexWriter(index, new JapaneseAnalyzer(), true); //文書の解析 for (int i = 0; i < filepath.length; i++) { Document doc = new Document(); //ファイルの登録 doc.add(Field.UnIndexed(quot;urlquot;, filepath[i])); Reader reader = new FileReader(filepath[i]); //文書内容の登録 doc.add(Field.Text(quot;contentsquot;,reader)); writer.addDocument(doc); } //インデクサのクローズ writer.optimize(); writer.close();
  • 8. Luceneインデックス作成サンプ ル //インデックスに登録するファイルのあるディレクトリ File directory = new File(args[0]); String[] filepath = directory.list(); //インデックスの保存先 String index = args[1]; //インデクサの生成 IndexWriter writer = new IndexWriter(index, new JapaneseAnalyzer(), true); //文書の解析 for (int i = 0; i < filepath.length; i++) { Document doc = new Document(); //ファイルの登録 doc.add(Field.UnIndexed(quot;urlquot;, filepath[i])); Reader reader = new FileReader(filepath[i]); //文書内容の登録 doc.add(Field.Text(quot;contentsquot;,reader)); writer.addDocument(doc); } //インデクサのクローズ writer.optimize(); writer.close();
  • 9. Luceneインデックス作成サンプ ル //インデックスに登録するファイルのあるディレクトリ File directory = new File(args[0]); String[] filepath = directory.list(); //インデックスの保存先 String index = args[1]; //インデクサの生成 IndexWriter writer = new IndexWriter(index, new JapaneseAnalyzer(), true); //文書の解析 for (int i = 0; i < filepath.length; i++) { Document doc = new Document(); //ファイルの登録 doc.add(Field.UnIndexed(quot;urlquot;, filepath[i])); Reader reader = new FileReader(filepath[i]); //文書内容の登録 doc.add(Field.Text(quot;contentsquot;,reader)); writer.addDocument(doc); } //インデクサのクローズ writer.optimize(); writer.close();
  • 10. Lucene検索サンプル // インデックス読み込み IndexSearcher is = new IndexSearcher(quot;indexquot;); // クエリーパーサーの作成 QueryParser qp = new QueryParser(quot;contentquot;, new SimpleAnalyzer()); // 検索クエリーの準備 Query q = qp.parse(“SomeQueryquot;); // 検索を実行 Hits hs = is.search(q); // 検索結果を表示 System.out.println(hs.length() + quot; hit(s)quot;); for(int i=0; i<hs.length(); i++) { System.out.println(hs.doc(i).toString()); } is.close();
  • 11. Hadoopとは? • Googleの基盤ソフトウェアのクローン – Google File System – MapReduce • Yahoo Research の Doug Cutting氏が開発 – 元々はNutch Crawlerのサブプロジェクト – Dougの子供の持っているぬいぐるみの名前 • Javaで記述
  • 12. Hadoop参考文献 • Hadoop公式サイト – http://hadoop.apache.org/core/ – Wiki: http://wiki.apache.org/hadoop/ • インストール方法・チュートリアル・プレゼン資 料など • Hadoop解析資料 (拙著) • http://preferred.jp/pub/hadoop.html • Hadoop, hBaseで構築する大規模データ処 理システム on CodeZine (拙著) – http://codezine.jp/a/article/aid/2448.aspx
  • 13. MapReduceの実行フロー Map Data Reduce Data Shuffle Map Data Reduce Data Map Data
  • 14. Hadoopのスケーラビリティ • Scaling 4000 nodes at Yahoo! – http://developer.yahoo.net/blogs/hadoop/2008/09/sc aling_hadoop_to_4000_nodes_a.html • Hadoop wins Terabyte Sort Benchmark – http://developer.yahoo.net/blogs/hadoop/2008/07/a pache_hadoop_wins_terabyte_sort_benchmark.html • Hadoopで書いとけば、4000ノードぐらいま ではスケールするよ!
  • 15. 例: ワードカウント 入力文書: doc1 foo foo foo bar bar buzz Map Data Reduce Data Shuffle Map Data Reduce Data Map Data
  • 16. 例: ワードカウント 入力文書: doc1 foo foo foo bar bar buz Map Data doc1: foo Reduce Data doc1: foo Shuffle Map Data doc1: foo Reduce doc1: bar Data Map Data doc1: bar doc1: buz
  • 17. 例: ワードカウント 入力文書: doc1 foo foo foo bar bar buz doc1: foo doc1: foo Map Data Reduce Data doc1: foo doc1: bar Shuffle Map Data Reduce doc1: bar Data doc1: buz Map Data
  • 18. 例: ワードカウント 入力文書: doc1 foo foo foo bar bar buz doc1: foo foo: 1 doc1: foo foo: 1 Map Data Reduce Data doc1: foo bar: 1 doc1: bar foo: 1 Map Data Reduce doc1: bar bar: 1 Data doc1: buz buz: 1 Map Data
  • 19. 例: ワードカウント 入力文書: doc1 foo foo foo bar bar buz foo: 1 foo: 1 bar: <1, 1> Map Data buz: <1> Reduce Data bar: 1 foo: 1 Map Data foo: <1, 1, 1> Reduce bar: 1 Data buz: 1 Map Data
  • 20. 例: ワードカウント 入力文書: doc1 foo foo foo bar bar buz bar: <1, 1> Map Data buz: <1> Reduce Data Map Data foo: <1, 1, 1> Reduce Data Map Data
  • 21. 例: ワードカウント 入力文書: doc1 foo foo foo bar bar buz bar: <1, 1> bar: 2 Map Data buz: <1> buz: 1 Reduce Data Map Data foo: <1, 1, 1> foo: 3 Reduce Data Map Data
  • 22. 例: ワードカウント 入力文書: doc1 foo foo foo bar bar buz bar: 2 Map Data buz: 1 Reduce Data Map Data foo: 3 Reduce Data Map Data
  • 23. 作成する検索エンジンの仕組み 検索用ノード Lucene クロールしてきた文章 インデック ス1 Lucene url1: <html>… インデック url2: <html>… ス2 url3: <html>… Lucene Hadoopによる url4: <html>… 分散 インデック 分散インデックス url5: <html>… クエリー ス3 作成 url6: <html>… 発行 Lucene url7: <html>… インデック … ス4 Lucene インデック ス5
  • 24. Hadoopによる分散インデックス作 成 url1: <html>… Map Data url2: <html>… Reduce Data url3: <html>… Shuffle Map Data url4: <html>… Reduce Data url5: <html>… Map Data url6: <html>…
  • 25. Hadoopによる分散インデックス作 成 url1: <html>… Map Data url2: <html>… Reduce Data url3: <html>… Shuffle Map Data url4: <html>… Reduce Data url5: <html>… Map Data url6: <html>…
  • 26. Hadoopによる分散インデックス作 成 url1: <html>… Map Data url2: <html>… url1: <html>… url4: <html>… Reduce Data url5: <html>… url3: <html>… Shuffle Map Data url4: <html>… url2: <html>… Reduce url3: <html>… Data url6: <html>… url5: <html>… Map Data url6: <html>…
  • 27. Hadoopによる分散インデックス作 成 url1: <html>… Lucene url4: <html>… インデック Map Data url5: <html>… ス Reduce Data url2: <html>… Lucene Shuffle<html>… Map Data url3: インデック url6: <html>… ス Reduce Data Map Data
  • 28. Hadoopによる分散インデックス作 成 Lucene インデック Map Data ス Reduce Data Lucene Shuffle Map Data インデック ス Reduce Data Map Data
  • 29. Hadoopによる分散インデックス作 成 Lucene インデック Map Data ス Reduce Data Lucene インデック Shuffle Map Data ス Reduce Data Map Data
  • 30. Hadoopによる分散インデックス作 成 Lucene Map Data インデック ス Reduce Data Lucene Shuffle Map Data インデック ス Reduce Data Map Data
  • 31. 分散インデックス作成 (Mapフェーズ) // 何もしない public void map(Text key, Text value, OutputCollector<Text, Text> output, Reporter reporter) throws IOException { Text url = key; Text str = value; output.collect(url, str); }
  • 32. 分散インデックス作成 (Reduceフェーズ) public void reduce(Text key, Iterator<Text> values, OutputCollector<Text, Writable> output, Reporter reporter) throws IOException { // URL Text url = key; // 本文 Text str = values.next(); // ドキュメントを追加 Document doc = new Document(); doc.add(new Field(quot;urlquot;, url.toString(), Field.Store.YES, Field.Index.NO)); doc.add(new Field(quot;contentquot;, str.toString(), Field.Store.YES, Field.Index.TOKENIZED)); output.collect(url, new LuceneDocumentWrapper(doc)); }
  • 33. 分散インデックス作成 (Reduce終了フェーズ) public void close(final Reporter reporter) throws IOException { // 分散ファイルシステムに保存するための何か final Path perm = new Path(job.getOutputPath(), name); final Path temp = job.getLocalPath( “index/_” + Integer.toString(new Random().nextInt())); // インデックス作成 final IndexWriter writer = new IndexWriter( fs.startLocalOutput(perm, temp).toString(), new JapaneseAnalyzer(), true); try { writer.optimize(); writer.close(); fs.completeLocalOutput(perm, temp); // copy to dfs } finally { closed = true; } }
  • 34. 以上のコードを実行 • Hadoopのインストール – 今回は24 (dual core)台のクラスタを使用 • ビルド • 実行 – bin/hadoop jar indexer.ja net.kzk9.indexer in out • 分散ファイルシステムのoutというディレ クトリにLuceneインデックスが作成されて いる – 30Gのドキュメントで約2-3時間?
  • 35. 作成する検索エンジンの仕組み 検索用ノード Lucene クロールしてきた文章 インデック ここを作った ス1 Lucene url1: <html>… インデック url2: <html>… ス2 url3: <html>… Lucene Hadoopによる url4: <html>… 分散 インデック 分散インデックス url5: <html>… クエリー ス3 作成 url6: <html>… 発行 Lucene url7: <html>… インデック … ス4 Lucene インデック ス5
  • 36. 落ち穂拾い • 時間的にここまで • 残りのタスク – クエリー受け付け用のサーバーを用意 – 作成されたインデックスをそいつらに転送 – クライアントから各サーバーにクエリーを発 行
  • 37. とはいえ • 商用検索エンジンにするには絶対的に欠 けている要素 – ランキング – クローラー • OSSの分散検索エンジン – Nutch • OSSの検索エンジン • あんまり出来が良くない – Senna • 分散バージョンマダー?
  • 38. まとめ • Luceneの使い方を説明 • Hadoopの使い方を説明 • 組み合わせて分散でインデックスを作成 する方法を紹介
  • 39. おわり % wc -l indexer.java 145 indexer.java