<?xml version="1.0" encoding="utf-8"?>
<rdf:RDF
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns="http://purl.org/rss/1.0/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:cc="http://web.resource.org/cc/"
    xmlns:admin="http://webns.net/mvcb/"
    xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
    xml:lang="ja">

    <channel rdf:about="http://lucene.jugem.jp/?mode=rss">
    <title>関口宏司のLuceneブログ</title>
    <link>http://lucene.jugem.jp/</link>
    <description>OSS検索ライブラリのLuceneおよびそのサブプロジェクト（Solr/Tika/Mahoutなど）について</description>
    <dc:language>ja</dc:language>
    <admin:generatorAgent rdf:resource="http://jugem.jp/?v=1.0"/>
    <items>
      <rdf:Seq>
        <rdf:li rdf:resource="http://lucene.jugem.jp/?eid=371" />
        <rdf:li rdf:resource="http://lucene.jugem.jp/?eid=370" />
        <rdf:li rdf:resource="http://lucene.jugem.jp/?eid=369" />
        <rdf:li rdf:resource="http://lucene.jugem.jp/?eid=368" />
        <rdf:li rdf:resource="http://lucene.jugem.jp/?eid=367" />
        <rdf:li rdf:resource="http://lucene.jugem.jp/?eid=366" />
        <rdf:li rdf:resource="http://lucene.jugem.jp/?eid=365" />
        <rdf:li rdf:resource="http://lucene.jugem.jp/?eid=364" />
        <rdf:li rdf:resource="http://lucene.jugem.jp/?eid=363" />
        <rdf:li rdf:resource="http://lucene.jugem.jp/?eid=362" />
        <rdf:li rdf:resource="http://lucene.jugem.jp/?eid=361" />
        <rdf:li rdf:resource="http://lucene.jugem.jp/?eid=360" />
        <rdf:li rdf:resource="http://lucene.jugem.jp/?eid=359" />
        <rdf:li rdf:resource="http://lucene.jugem.jp/?eid=358" />
        <rdf:li rdf:resource="http://lucene.jugem.jp/?eid=357" />
      </rdf:Seq>
    </items>
    </channel>

  <item rdf:about="http://lucene.jugem.jp/?eid=371">
    <link>http://lucene.jugem.jp/?eid=371</link>
    <title>（メモ）ElasticSearch</title>
    <description>Luceneを使って作られた、JSON over HTTPで登録／検索できる検索エンジン：

ElasticSearch
http://www.elasticsearch.com/products/elasticsearch/
curl -XPUTで登録し、curl -XGETで検索している様子をビデオデモで見られる。</description>
<content:encoded><![CDATA[
Luceneを使って作られた、JSON over HTTPで登録／検索できる検索エンジン：<br />
<br />
ElasticSearch<br />
<a href="http://www.elasticsearch.com/products/elasticsearch/" target="_blank">http://www.elasticsearch.com/products/elasticsearch/</a><br /><br />
curl -XPUTで登録し、curl -XGETで検索している様子を<a href="http://www.elasticsearch.com/videos/" target="_blank">ビデオデモで見られる</a>。
]]></content:encoded>
    <dc:subject>Luceneツール</dc:subject>
    <dc:date>2010-02-09T08:21:00+09:00</dc:date>
    <dc:creator>関口宏司</dc:creator>
    <dc:publisher>JUGEM</dc:publisher>
    <dc:rights>関口宏司</dc:rights>
<taxo:topics>
<rdf:Bag>
<rdf:li rdf:resource="http://jugem.jp/contents/theme.php?theme=12" />
</rdf:Bag>
</taxo:topics>
  </item>

  <item rdf:about="http://lucene.jugem.jp/?eid=370">
    <link>http://lucene.jugem.jp/?eid=370</link>
    <title>Lucene 3.1以降ではAnalyzerにLuceneのバージョンを渡す件</title>
    <description>Lucene 3.1以降ではほとんどのAnalyzerのコンストラクタがVersion（Enum）を引数に取るので、ユーザは使用するLuceneのバージョンを渡さなければいけない。MLにAnalyzerを作成するときのパターンが載っていたので転記する：



final Analyzer createAnalyzer(String ...</description>
<content:encoded><![CDATA[
Lucene 3.1以降ではほとんどのAnalyzerのコンストラクタがVersion（Enum）を引数に取るので、ユーザは使用するLuceneのバージョンを渡さなければいけない。MLにAnalyzerを作成するときのパターンが載っていたので転記する：<br /><br />

<div class="code_sample">
<pre>
final Analyzer createAnalyzer(String className, Version matchVersion) throws Exception &#123;
  final Class<? extends Analyzer> clazz = Class.forName(className).asSubclass(Analyzer.class);
  try &#123;
    // first try to use a ctor with version parameter (needed for many new Analyzers that have no default one anymore
    return clazz.getConstructor(Version.class).newInstance(matchVersion);
  &#125; catch (NoSuchMethodException nsme) &#123;
    // otherwise use default ctor
    return clazz.newInstance();
  &#125;
&#125;
</pre>
</div>
<br /><br />
ネタもと：<br />
<a href="http://old.nabble.com/Having-a-default-constructor-in-Analyzers-td27490616.html" target="_blank">http://old.nabble.com/Having-a-default-constructor-in-Analyzers-td27490616.html</a>
]]></content:encoded>
    <dc:subject>Luceneクラス解説</dc:subject>
    <dc:date>2010-02-08T09:19:08+09:00</dc:date>
    <dc:creator>関口宏司</dc:creator>
    <dc:publisher>JUGEM</dc:publisher>
    <dc:rights>関口宏司</dc:rights>
<taxo:topics>
<rdf:Bag>
<rdf:li rdf:resource="http://jugem.jp/contents/theme.php?theme=12" />
</rdf:Bag>
</taxo:topics>
  </item>

  <item rdf:about="http://lucene.jugem.jp/?eid=369">
    <link>http://lucene.jugem.jp/?eid=369</link>
    <title>@lucene.experimental と @lucene.internal Javadocタグ</title>
    <description>これまで書き方が統一されていなかったLucene Javadocにおける試験的なAPIと内部使用目的のAPIのWARNINGメッセージが、AntのJavadocタスクの機能（javadocコマンドの-tagオプション）を使って統一された。試験的なAPIとは、publicなクラスやメソッドであっても、「これは...</description>
<content:encoded><![CDATA[
これまで書き方が統一されていなかったLucene Javadocにおける試験的なAPIと内部使用目的のAPIのWARNINGメッセージが、AntのJavadocタスクの機能（javadocコマンドの-tagオプション）を使って統一された。試験的なAPIとは、publicなクラスやメソッドであっても、「これは試験的なAPIであり、将来互換性を保たない方法で変更される恐れがあります」といった統一されたWARNINGメッセージがJavadocに表示される。またLucene内部使用目的のAPIも類似のメッセージが表示される：<br /><br />

<a href="https://issues.apache.org/jira/browse/LUCENE-2209" target="_blank">https://issues.apache.org/jira/browse/LUCENE-2209</a>
]]></content:encoded>
    <dc:subject>Luceneクラス解説</dc:subject>
    <dc:date>2010-02-01T09:36:17+09:00</dc:date>
    <dc:creator>関口宏司</dc:creator>
    <dc:publisher>JUGEM</dc:publisher>
    <dc:rights>関口宏司</dc:rights>
<taxo:topics>
<rdf:Bag>
<rdf:li rdf:resource="http://jugem.jp/contents/theme.php?theme=12" />
</rdf:Bag>
</taxo:topics>
  </item>

  <item rdf:about="http://lucene.jugem.jp/?eid=368">
    <link>http://lucene.jugem.jp/?eid=368</link>
    <title>ヒープ消費量を計算するクラス（2.9）</title>
    <description>LUCENE-1749の一部としてヒープの消費量を計算するユーティリティクラスRamUsageEstimatorがLucene 2.9に追加されたのでその使い方を紹介しよう。簡単なのでいきなりサンプルプログラムを示す：



public class TestRamUsage &amp;#123;

  private final String name;...</description>
<content:encoded><![CDATA[
<a href="https://issues.apache.org/jira/browse/LUCENE-1749" target="_blank">LUCENE-1749</a>の一部としてヒープの消費量を計算するユーティリティクラスRamUsageEstimatorがLucene 2.9に追加されたのでその使い方を紹介しよう。簡単なのでいきなりサンプルプログラムを示す：<br /><br />

<div class="code_sample">
<pre>
public class TestRamUsage &#123;

  private final String name;
  private TestRamUsage tru;
  
  public TestRamUsage( String name )&#123;
    this.name = name;
  &#125;
  
  public static void main(String[] args) &#123;
    RamUsageEstimator rue = new RamUsageEstimator();

    TestRamUsage mike = new TestRamUsage( "Mike" );
    System.out.println( "size of mike = " + rue.estimateRamUsage( mike ) );

    TestRamUsage christian = new TestRamUsage( "Christian" );
    System.out.println( "size of christian = " + rue.estimateRamUsage( christian ) );
    
    mike.tru = christian;
    System.out.println( "size of mike = " + rue.estimateRamUsage( mike ) );
  &#125;

&#125;
</pre>
</div>
<br /><br />
これを実行すると、次のように表示される：<br /><br />

<div class="run_sample">
<pre>
size of mike = 16
size of christian = 16
size of mike = 32
</pre>
</div>
<br /><br />

2回目の"mike"のサイズが2倍になっているのは、mikeのメンバ変数にchristianを代入したためである。このようにRamUsageEstimatorはオブジェクトのツリーをたどってそのオブジェクトの全消費量を示してくれる。<br /><br />

なお、"mike"と"christian"でnameの長さが違うのに同じサイズになっているのは、オブジェクトがStringの場合、デフォルトでintern()したものと比較し、オブジェクトとintern()したものの参照が同じならばサイズとして算入しないようになっているためである。この動作を変えるには、RamUsageEstimatorのコンストラクタにfalseを渡してやればよい。すると、実行結果は次のようになる：<br /><br />

<div class="run_sample">
<pre>
size of mike = 64
size of christian = 74
size of mike = 138
</pre>
</div>


]]></content:encoded>
    <dc:subject>Luceneクラス解説</dc:subject>
    <dc:date>2010-01-18T07:02:31+09:00</dc:date>
    <dc:creator>関口宏司</dc:creator>
    <dc:publisher>JUGEM</dc:publisher>
    <dc:rights>関口宏司</dc:rights>
<taxo:topics>
<rdf:Bag>
<rdf:li rdf:resource="http://jugem.jp/contents/theme.php?theme=12" />
</rdf:Bag>
</taxo:topics>
  </item>

  <item rdf:about="http://lucene.jugem.jp/?eid=367">
    <link>http://lucene.jugem.jp/?eid=367</link>
    <title>（メモ）Antiword</title>
    <description>http://www.winfield.demon.nl/

Wordファイルからテキストデータを抽出するツール。対応プラットフォームが充実しており、VMS、Zaurus、BeOSまでをもサポートしている。</description>
<content:encoded><![CDATA[
<a href="http://www.winfield.demon.nl/" target="_blank">http://www.winfield.demon.nl/</a><br /><br />

Wordファイルからテキストデータを抽出するツール。対応プラットフォームが充実しており、VMS、Zaurus、BeOSまでをもサポートしている。
]]></content:encoded>
    <dc:subject>Luceneツール</dc:subject>
    <dc:date>2010-01-12T08:23:20+09:00</dc:date>
    <dc:creator>関口宏司</dc:creator>
    <dc:publisher>JUGEM</dc:publisher>
    <dc:rights>関口宏司</dc:rights>
<taxo:topics>
<rdf:Bag>
<rdf:li rdf:resource="http://jugem.jp/contents/theme.php?theme=12" />
</rdf:Bag>
</taxo:topics>
  </item>

  <item rdf:about="http://lucene.jugem.jp/?eid=366">
    <link>http://lucene.jugem.jp/?eid=366</link>
    <title>THIS IS IT</title>
    <description>&quot;THIS IS IT&quot;といえばマイケル・ジャクソンの映画として有名だが、我々検索業界関係者の間では「ストップワードだけからなる文書」として2009年にたびたびとりあげられた格好のサンプルデータとなったものである。

ところで映画／DVDなどのタイトルには、このようにス...</description>
<content:encoded><![CDATA[
"THIS IS IT"といえばマイケル・ジャクソンの映画として有名だが、我々検索業界関係者の間では「ストップワードだけからなる文書」として2009年にたびたびとりあげられた格好のサンプルデータとなったものである。<br /><br />

ところで映画／DVDなどのタイトルには、このようにストップワードが重要な要素となっているものが少なくなく、単純にStopFilterを適用するわけにはいかない場合がある。そんなときはStopFilterをとりあえず適用しないという手もあるが、そうすると"the", "a", "it"などを含む文書は数が多く、そこから今度はユーザクエリのフレーズにマッチしない文書を取り除くのにコストがかかってしまう。<br /><br />

このような場合に便利なのがShingleFilterである。"shingle"とはワード単位のN-gramのことで、"THIS IS IT"に2-gramのShingleFilterを適用すると、"THIS IS", "IS IT"というトークンを出力してくれるため、単独のトークンよりもdocFreqが小さく抑えられ、性能を維持しつつタイトルを検索できるようになる。
]]></content:encoded>
    <dc:subject>Luceneクラス解説</dc:subject>
    <dc:date>2009-12-31T11:08:16+09:00</dc:date>
    <dc:creator>関口宏司</dc:creator>
    <dc:publisher>JUGEM</dc:publisher>
    <dc:rights>関口宏司</dc:rights>
<taxo:topics>
<rdf:Bag>
<rdf:li rdf:resource="http://jugem.jp/contents/theme.php?theme=12" />
</rdf:Bag>
</taxo:topics>
  </item>

  <item rdf:about="http://lucene.jugem.jp/?eid=365">
    <link>http://lucene.jugem.jp/?eid=365</link>
    <title>IndexableBinaryStringTools (2.9)</title>
    <description>Luceneは当初からバイナリデータをインデックスに登録できたが、それは単にバイナリデータを出し入れするだけであり、バイナリデータを検索の対象にするものではなかった。

Lucene 2.9で追加されたIndexableBinaryStringToolsクラスを使うとバイナリデータ（byte[]）を...</description>
<content:encoded><![CDATA[
Luceneは当初からバイナリデータをインデックスに登録できたが、それは単にバイナリデータを出し入れするだけであり、バイナリデータを検索の対象にするものではなかった。<br /><br />

Lucene 2.9で追加されたIndexableBinaryStringToolsクラスを使うとバイナリデータ（byte[]）をソートオーダーを維持したまま、インデックスに索引付けできるStringに変換できる。これにより、バイナリデータも検索できるようになった。もっともこのクラスが導入された動機は、ロケールに依存したトークンのソートを行うためにCollatorを使った場合、さらにソートの高速化のためにCollationKeyによって変換されたバイナリデータを索引付けしたいがためのものである。<br /><br />

関連JIRA：<br /><br />
IndexableBinaryStringToolsクラスの導入<br />
<a href="https://issues.apache.org/jira/browse/LUCENE-1434" target="_blank">https://issues.apache.org/jira/browse/LUCENE-1434</a><br /><br />

トークンをCollationKeyで変換、IndexableBinaryStringToolsでエンコードするCollationKeyFilterの導入<br />
<a href="https://issues.apache.org/jira/browse/LUCENE-1435" target="_blank">https://issues.apache.org/jira/browse/LUCENE-1435</a><br /><br />

Lucene 2.9ではCollationKeyFilterはcontrib/collationの下にJDKのCollatorを使った実装と、ICUのものを使った実装が同居していたが、現在開発中のLucene 3.1ではJDKのものをLucene coreに移動し、ICUライブラリに依存する実装はcontrib/icuというディレクトリが新設されてそこに移動された。これにともない、contrib/collationディレクトリは廃止された：<br /><br />

<a href="https://issues.apache.org/jira/browse/LUCENE-2124" target="_blank">https://issues.apache.org/jira/browse/LUCENE-2124</a><br /><br />

このような背景のIndexableBinaryStringToolsではあるが、あえてバイナリデータを登録（索引付け）し、検索してみると、次のようなプログラムになる：<br /><br />

<div class="code_sample">
<pre>
public class TestIndexableBinaryStringTools &#123;

  static Directory dir = new RAMDirectory();
  static Analyzer analyzer = new WhitespaceAnalyzer();
  
  public static void main(String[] args) throws IOException &#123;
    makeIndex();
    searchIndex();
  &#125;

  static void makeIndex() throws IOException &#123;
    IndexWriter writer = new IndexWriter( dir, analyzer, true, MaxFieldLength.LIMITED );
    for( int i = 0; i < 3; i++ )&#123;
      Document doc = new Document();
      doc.add( new Field( "id", Integer.toString( i ), Store.YES, Index.ANALYZED ) );
      doc.add( new Field( "data", bytes2String( new byte[]&#123; (byte)i &#125; ), Store.YES, Index.NOT_ANALYZED ) );
      writer.addDocument( doc );
    &#125;
    writer.close();
  &#125;
  
  static String bytes2String( byte[] data )&#123;
    CharBuffer charBuffer = IndexableBinaryStringTools.encode( ByteBuffer.wrap( data ) );
    return new String( charBuffer.array() );
  &#125;
  
  static void searchIndex() throws IOException &#123;
    IndexSearcher searcher = new IndexSearcher( dir );
    Query query = new TermQuery( new Term( "data", bytes2String( new byte[]&#123; 2 &#125;) ) );
    TopDocs docs = searcher.search( query, 10 );
    for( ScoreDoc scoreDoc : docs.scoreDocs )&#123;
      Document doc = searcher.doc( scoreDoc.doc );
      System.out.println( "id = " + doc.get( "id" ) );
      System.out.println( "data = " + string2Bytes( doc.get( "data" ) )[0] );
    &#125;
    searcher.close();
  &#125;
  
  static byte[] string2Bytes( String s )&#123;
    ByteBuffer byteBuffer = IndexableBinaryStringTools.decode( CharBuffer.wrap( s.toCharArray() ) );
    return byteBuffer.array();
  &#125;
&#125;
</pre>
</div>

]]></content:encoded>
    <dc:subject>Luceneクラス解説</dc:subject>
    <dc:date>2009-12-30T14:20:38+09:00</dc:date>
    <dc:creator>関口宏司</dc:creator>
    <dc:publisher>JUGEM</dc:publisher>
    <dc:rights>関口宏司</dc:rights>
<taxo:topics>
<rdf:Bag>
<rdf:li rdf:resource="http://jugem.jp/contents/theme.php?theme=12" />
</rdf:Bag>
</taxo:topics>
  </item>

  <item rdf:about="http://lucene.jugem.jp/?eid=364">
    <link>http://lucene.jugem.jp/?eid=364</link>
    <title>（メモ）Free live video streaming of ApacheCon US 2009</title>
    <description>http://streaming.linux-magazin.de/en/program-apachecon-us-2009.htm</description>
<content:encoded><![CDATA[
<a href="http://streaming.linux-magazin.de/en/program-apachecon-us-2009.htm" target="_blank">http://streaming.linux-magazin.de/en/program-apachecon-us-2009.htm</a>
]]></content:encoded>
    <dc:subject>Luceneセミナー</dc:subject>
    <dc:date>2009-12-16T00:24:50+09:00</dc:date>
    <dc:creator>関口宏司</dc:creator>
    <dc:publisher>JUGEM</dc:publisher>
    <dc:rights>関口宏司</dc:rights>
<taxo:topics>
<rdf:Bag>
<rdf:li rdf:resource="http://jugem.jp/contents/theme.php?theme=12" />
</rdf:Bag>
</taxo:topics>
  </item>

  <item rdf:about="http://lucene.jugem.jp/?eid=363">
    <link>http://lucene.jugem.jp/?eid=363</link>
    <title>Solr SVNリポジトリにクラウドブランチ登場！</title>
    <description>http://svn.apache.org/viewvc?view=revision&amp;revision=888480
</description>
<content:encoded><![CDATA[
<a href="http://svn.apache.org/viewvc?view=revision&revision=888480" target="_blank">http://svn.apache.org/viewvc?view=revision&revision=888480</a>

]]></content:encoded>
    <dc:subject>Solr</dc:subject>
    <dc:date>2009-12-09T09:17:00+09:00</dc:date>
    <dc:creator>関口宏司</dc:creator>
    <dc:publisher>JUGEM</dc:publisher>
    <dc:rights>関口宏司</dc:rights>
<taxo:topics>
<rdf:Bag>
<rdf:li rdf:resource="http://jugem.jp/contents/theme.php?theme=12" />
</rdf:Bag>
</taxo:topics>
  </item>

  <item rdf:about="http://lucene.jugem.jp/?eid=362">
    <link>http://lucene.jugem.jp/?eid=362</link>
    <title>（検索）APIの後方互換性チェックテストコード</title>
    <description>Luceneのテストコードは通常JUnitを使って書かれた単体テストになっているが、検索パッケージには&quot;JustCompile&quot;というファイル名で始まる「APIの後方互換性をチェックするためだけの実行されないテストコード」がある：



&amp;#36; find . -name JustCompile&amp;yen;*.java...</description>
<content:encoded><![CDATA[
Luceneのテストコードは通常JUnitを使って書かれた単体テストになっているが、検索パッケージには"JustCompile"というファイル名で始まる「APIの後方互換性をチェックするためだけの実行されないテストコード」がある：<br /><br />

<div class="run_sample">
<pre>
&#36; find . -name JustCompile&yen;*.java
./test/org/apache/lucene/search/function/JustCompileSearchSpans.java
./test/org/apache/lucene/search/JustCompileSearch.java
./test/org/apache/lucene/search/spans/JustCompileSearchSpans.java
</pre>
</div>
<br /><br />

"JustCompile"テストコードはそれぞれのパッケージのpublicインタフェースおよび抽象クラスをimplementsまたはextendsした具象クラスを用意している。このしくみにより、将来、インタフェースに新しいメソッドや抽象クラスに新しい抽象メソッドがうっかり加えられると、コンパイルエラーになることで警告できるようにしている。
]]></content:encoded>
    <dc:subject>Luceneクラス解説</dc:subject>
    <dc:date>2009-12-07T23:59:36+09:00</dc:date>
    <dc:creator>関口宏司</dc:creator>
    <dc:publisher>JUGEM</dc:publisher>
    <dc:rights>関口宏司</dc:rights>
<taxo:topics>
<rdf:Bag>
<rdf:li rdf:resource="http://jugem.jp/contents/theme.php?theme=12" />
</rdf:Bag>
</taxo:topics>
  </item>

  <item rdf:about="http://lucene.jugem.jp/?eid=361">
    <link>http://lucene.jugem.jp/?eid=361</link>
    <title>クラウド化するSolr 1.5</title>
    <description>SolrプロジェクトのリーダーYonik Seeley氏がSolr開発者メーリングリストの中で、「Solr 1.5はクラウド対応をしようぜ！」と宣言し盛り上がりを見せ始めている：
http://old.nabble.com/Solr-1.5---The-Cloud-Edition!-td26635459.html

以下に本日現在のSolrクラウド...</description>
<content:encoded><![CDATA[
SolrプロジェクトのリーダーYonik Seeley氏がSolr開発者メーリングリストの中で、「Solr 1.5はクラウド対応をしようぜ！」と宣言し盛り上がりを見せ始めている：<br /><br />
<a href="http://old.nabble.com/Solr-1.5---The-Cloud-Edition!-td26635459.html" target="_blank">http://old.nabble.com/Solr-1.5---The-Cloud-Edition!-td26635459.html</a>
<br /><br />
以下に本日現在のSolrクラウド専用ページ<a href="http://wiki.apache.org/solr/SolrCloud" target="_blank">http://wiki.apache.org/solr/SolrCloud</a>の拙訳を掲載する：<br />
<br />


<span style="font-size:large;"><strong>ハイレベルな設計目標</strong></span><br/>

SolrCloudの長期目標を示す。ここに掲げる特徴の多くは最初のバージョンから提供されるものではないが、長期的な目標を掲げて設計を行う。
<br /><br />

<strong>高可用性と耐障害性</strong><br /><br />

ロードバランサーを不要とする。単一障害点を排除する（つまり、後述のZooKeeperスキーマのようなしくみを最小限の変更だけであとからこの特徴を追加できるようなデザインを出発点としたい）。
<br /><br />

<strong>クラスターのリサイズとリバランス</strong><br /><br />

クラスターを拡張したり、ホットスポットをリバランスさせるためにシャードはリサイズできなければならない。既存のシャードは分割したり新しいサーバを割り当てたりできる。
<br /><br />

<strong>クライアントはクラスターのレイアウトを知らなくとも良いこと</strong><br /><br />

ブラウザのようなシンプルなクライアントはクラスター内のどのSolr検索サーバにもリクエストを送ることができる。そしてその検索サーバはクラスター全体に対して分散検索が実行できなくてはならない。これにはクライアントに結果を返すためのロードバランシングとフェイルオーバーも含む。
<br /><br />

<strong>オープンなAPI</strong><br /><br />

ZooKeeperスキーマはマスターノード以外の他のソフトウェアコンポーネントからも、ZooKeeperを通じてクラスターを調査したり変更したりできるような設計がなされるべきである。他のSolrサーバと通信することなくZooKeeper内に正しいznode/ファイルを作成することで、新しいコレクションを作成するようなタスクを最終的に達成する。
<br /><br />

<strong>いろいろなレベルのカスタムクラスターをサポート</strong><br /><br />

ユーザ管理とSolr管理の間の自由度を大きくする。ZooKeeper内の一組のサーバを定義されたインデックス（シャードまたは完全なコピー）とともに管理し、クライアントの検索用途だけに使うこともできるし、一方で昔ながらのマスター／スレーブ構成を使うことも可能とする。
<br /><br />

<strong>ユーザ定義のパーティショニングをサポート</strong><br /><br />

地理的、時間、ユーザ、・・・などにドキュメントを分割することにより、クラスタの一部だけを検索可能にすることで、検索性能を向上させることができる。これは高度なオペレーション（自動によるドキュメント＝＞シャード割り当て（おそらくユーザ定義のハッシュ関数により行われる）、インデックスリバランシング、単一障害点の排除など）によりもたらされる一例に過ぎない。
<br /><br />

<span style="font-size:large;">ZooKeeperでモデル化／登録したいエンティティ</span><br/>

<strong>ホスト</strong><br /><br />

<ul>
<li>実際の物理的／仮想化マシン</li>
<li>OS、RAM、ディスク</li>
<li>マシンにどの程度の負荷がかけられるかの測定基準</li>
</ul>
<br /><br />

<strong>ノード</strong><br /><br />

<ul>
<li>Solr（マルチコア／シングルコア問わず）を実行している単一のJVM</li>
</ul>
<br /><br />

<strong>コレクション</strong><br /><br />

<ul>
<li>同じスキーマを共有しているドキュメントのコレクション</li>
</ul>
<br /><br />

<strong>シャード</strong><br /><br />

<ul>
<li>コレクションの一片</li>
<li>シャードはレプリカ（コピー）を持っていることがある。部分的に他のシャードと重なることがありうる</li>
</ul>
<br /><br />

<strong>コア</strong><br /><br />

<ul>
<li>ひとつのSolrCore（他によい名前はあるか？）</li>
<li>コアとシャードが1対1にマッピングされているとき、冗長構成となる</li>
</ul>
<br /><br />

<strong>ロール</strong><br /><br />

<ul>
<li>ロールはコアであり、マスタであり、検索ノードであり、スペルチェッカーノード、などである</li>
<li>ロールから他の設定または設定オーバーライドにマップするための汎用的な方法を求める</li>
</ul>
<br /><br />

<strong>ネットワークトポロジ</strong><br /><br />

<ul>
<li>スイッチ、ラック、データセンターなど</li>
</ul>
<br /><br />

<span style="font-size:large;"><strong>ZooKeeperスキーマ</strong></span><br/>

<span style="font-size:large;">モデルと状態</span><br/>

ZooKeeperに含ませたい論理的に異なる2つのタイプのデータがある：
<br /><br />

「モデル」：クラスタとシステムのゴール／ターゲットを表現する。
<br /><br />

「状態」：それを包含するクラスタとシステムの現在の実際の状態を表現する。
<br /><br />

マネージャはよく定義されたモデルの変更を作成できる。サーバはそのモデルに適合する場合に自身の状態を応答する。
<br /><br />

<span style="font-size:large;">複数のSolrクラスター</span><br/>

単一のSolrクラスターは既存のZooKeeperクラスターを利用できなければならない。そして複数のSolrクラスターは単一のZooKeeperクラスターと共存できなければならない。
<br /><br />

ひとつのアイディア：ZooKeeperクラスターを指し任意のプレフィックスを含む設定URLを使えば簡単にできそう。
<br /><br />

<span style="font-size:large;">シャード識別</span><br/>

シャードを識別するための2つの方法が必要である。
<br /><br />

将来的に複雑なクラスターの機能として、Solrは特定のドキュメントがどこにあるか知る必要がある。シャードに含まれるドキュメントはIDの範囲により特定される。ここでのIDとは、ユニークキーフィールドではなくなにかのハッシュコードやユーザ提供によるものとする。
<br /><br />

ほとんどの基本的なケースでは、クラスターの外でインデックスを作ることになるだろう。この場合、我々はどのドキュメントがどのシャードにあるかを関知しない。しかし、ひとつのシャードが他のシャードの単純なレプリカであるという事実を識別する方法が我々には必要である。
<br /><br />

<span style="font-size:large;">レイアウト</span><br/>

ZooKeeper内の仮想ファイルシステム（スキーマなど）がどのようなものかについてのブレインストーミング：
<br /><br />

mycluster/hosts
<br /><br />

* 192.168.0.10<br/>
# どのようにホストを識別するか？ホスト名？IP？ホストは1つ以上のIPを持つ。複数を扱うべきか？
<br /><br />

mycluster/configs/collection1_config/v1/
<br /><br />

* solrconfig.xml, schema.xml, stopwords.txt,など。
<br /><br />

collections/collection1/
<br /><br />

* config=collection1_config 
# 複数のコレクションが同じ設定を利用できるよう明示する<br />
# コレクションは直接シャードのURLを指すべきか？（方法その1）
<br /><br />

/collections/collection1/shards
<br /><br />

* localhost:8983/solr/collection1=shardX,shardY,shardZ<br/>
* localhost:7574/solr/collection1=shardX,shardZ 
<br /><br />
# またはおそらくノードIDを単に指定する（このような形式：localhost:8983? localhost:8983/solr?）<br/>
# そして"collection1"のようにしてコレクション名であることを暗黙の了解とする？<br/>
# それはおそらくある制限をもたらしてしまう。フェデレーション検索をしたい場合どうなる？<br/>
# コレクションに属するノードをリストアップする、各ノードが保持するシャード込みで？（方法その2）
<br /><br />

/collections/collection1/nodes/localhost:8983/
<br /><br />

* shards/ # ノードlocalhost:8983が現在属するこのコレクションのシャード<br/>
* X=/solr/collection1 # ノードIDからの関連URL<br/>
* Y=/solr/collection1<br/>
* Z=/solr/collection1<br/>
# インデックス（シャード）のバージョン（最後のアップデート日時など）を記録できなければならない。
<br />
# 方法その3は各ノードをリストアップするシャードをノード自身のモデルに移動できる。
<br /><br />

<span style="font-size:large;">その他疑問点</span><br/>

コレクションごとに単一のマスター（クラスターマネージャのこと、Solrマスターではない）が存在するか、またはクラスター内のすべてのコレクションにひとつのマスターか？
<br /><br />

<span style="font-size:large;"><strong>参考文献</strong></span><br/>

<a href="http://sourceforge.net/mailarchive/forum.php?forum_name=bailey-developers" target="_blank">http://sourceforge.net/mailarchive/forum.php?forum_name=bailey-developers</a><br/>
（関口：<a href="http://lucene.jugem.jp/?eid=247" target="_blank">Baileyについては以前記事を書きました</a>）
<br /><br />
<a href="http://www.allthingsdistributed.com/2007/10/amazons_dynamo.html" target="_blank">http://www.allthingsdistributed.com/2007/10/amazons_dynamo.html</a>
<br /><br />

]]></content:encoded>
    <dc:subject>Solr</dc:subject>
    <dc:date>2009-12-04T11:15:36+09:00</dc:date>
    <dc:creator>関口宏司</dc:creator>
    <dc:publisher>JUGEM</dc:publisher>
    <dc:rights>関口宏司</dc:rights>
<taxo:topics>
<rdf:Bag>
<rdf:li rdf:resource="http://jugem.jp/contents/theme.php?theme=12" />
</rdf:Bag>
</taxo:topics>
  </item>

  <item rdf:about="http://lucene.jugem.jp/?eid=360">
    <link>http://lucene.jugem.jp/?eid=360</link>
    <title>2位じゃダメなんでしょうか？</title>
    <description>「1位にしなければいけない理由はなんでしょうか。2位じゃダメなんでしょうか？」

「・・・・」

これは事業仕分け作業においてスーパーコンピューターの処理能力について激しく議論をする蓮舫参議院議員と文科省官僚とのやりとり・・・ではない。私と顧客とのやりと...</description>
<content:encoded><![CDATA[
「1位にしなければいけない理由はなんでしょうか。2位じゃダメなんでしょうか？」<br /><br />

「・・・・」<br /><br />

これは事業仕分け作業においてスーパーコンピューターの処理能力について激しく議論をする蓮舫参議院議員と文科省官僚とのやりとり・・・ではない。私と顧客とのやりとりの一幕である。もちろん、1位2位というのは検索結果ランキングのことだ。検索結果ランキングのカスタマイズは顧客の要望がもっとも集中するものの一つである。特定のページのランキングを意図的に1位にすることは簡単だ。しかし、本当に1位にしたいのか、その理由は、と聞いていくと案外はっきりした理由は出てこないものである。そのようなときは簡単に1位にしたりせず、Lucene/Solrのデフォルトにゆだねてしばらく運用した方がよい。蓮舫議員も後にテレビのインタビューに応えて「あのように聞けば1位にしなければいけない理由が語られると思った」と述べている。私も同感である。<br /><br />

しかし先日、ついに堂々と要求を述べる顧客に会った。<br /><br />

「1位じゃなきゃダメなんです」<br /><br />

理由はよくわからなかった。しかし毅然とした態度は私に十分訴えるものがあった。1位にする必要があった。<br /><hr/><br/>

単純にboostをあげると常に上位表示することができるが、インデックスにboostを記録する必要があるため、変更処理が重くなる。そしてその用が済んだとき（キャンペーンの終了など）、boostをリセットするにも重い処理をしなければならない。そんなときは、ある検索語が使われたときにだけ上位表示させることが可能なSolrの機能を検討しよう。それはQueryElevationComponentである。面白いのは、その検索語は上位表示させたいページの文書に必ずしも含まれていなくてもよいことである。インデックスを変更することなく、軽快に上位表示／リセットを実行することができる。
<br /><br /><br /><br />
<a href="http://www.rondhuit.com/training.html" target="_blank">トレーニングコース「速習 Solr 1.4」は12月16日(水)いよいよ千秋楽、12月2日(水)まで受講者募集中！</a>
]]></content:encoded>
    <dc:subject>Solr</dc:subject>
    <dc:date>2009-11-28T22:38:00+09:00</dc:date>
    <dc:creator>関口宏司</dc:creator>
    <dc:publisher>JUGEM</dc:publisher>
    <dc:rights>関口宏司</dc:rights>
<taxo:topics>
<rdf:Bag>
<rdf:li rdf:resource="http://jugem.jp/contents/theme.php?theme=12" />
</rdf:Bag>
</taxo:topics>
  </item>

  <item rdf:about="http://lucene.jugem.jp/?eid=359">
    <link>http://lucene.jugem.jp/?eid=359</link>
    <title>Lucene 3.0.0のリリース</title>
    <description>本日Java 5の各種機能を使ったLucene 3.0.0がリリースされた。Lucene 2.9でdeprecatedとなったAPIは3.0では削除されたので、deprecated APIを使っていたアプリケーションは、代替のAPIを使わなければコンパイルできない。</description>
<content:encoded><![CDATA[
本日<a href="http://lucene.jugem.jp/?eid=353" target="_blank">Java 5の各種機能</a>を使ったLucene 3.0.0がリリースされた。Lucene 2.9でdeprecatedとなったAPIは3.0では削除されたので、deprecated APIを使っていたアプリケーションは、代替のAPIを使わなければコンパイルできない。
]]></content:encoded>
    <dc:subject>Luceneリリース</dc:subject>
    <dc:date>2009-11-26T20:13:28+09:00</dc:date>
    <dc:creator>関口宏司</dc:creator>
    <dc:publisher>JUGEM</dc:publisher>
    <dc:rights>関口宏司</dc:rights>
<taxo:topics>
<rdf:Bag>
<rdf:li rdf:resource="http://jugem.jp/contents/theme.php?theme=12" />
</rdf:Bag>
</taxo:topics>
  </item>

  <item rdf:about="http://lucene.jugem.jp/?eid=358">
    <link>http://lucene.jugem.jp/?eid=358</link>
    <title>SSDを効果的に使い検索を高速化する方法</title>
    <description>http://old.nabble.com/Distributing-index-over-N-disks-td26504452.html

Lucene/Solrのインデックスが完成されたもので変更がない（追加／更新／削除がなく、マージもされない）ならば、SSDを用意して.frqファイルと.prxファイルを配置し、残りのインデックスファイ...</description>
<content:encoded><![CDATA[
<a href="http://old.nabble.com/Distributing-index-over-N-disks-td26504452.html" target="_blank">http://old.nabble.com/Distributing-index-over-N-disks-td26504452.html</a><br /><br />

Lucene/Solrのインデックスが完成されたもので変更がない（追加／更新／削除がなく、マージもされない）ならば、SSDを用意して.frqファイルと.prxファイルを配置し、残りのインデックスファイルはHDDに配置する。そしてHDDのインデックスディレクトリにはSSDへのシンボリックリンクを配置する。<br /><br />

.frqファイルには各TermのDocumentごとの出現数が記録されている。.prxファイルにはさらにその詳細としてその出現毎のフィールドにおけるTermの位置情報が記録されている。いずれもomitTfがfalseのときに.fdtファイルに次いでサイズが大きく、また検索実行時に頻繁にアクセスされるため、これらのファイルを選択的にSSDに配置することで検索コストパフォーマンスを最大化できると期待できる。
]]></content:encoded>
    <dc:subject>Luceneインデックス</dc:subject>
    <dc:date>2009-11-26T09:56:32+09:00</dc:date>
    <dc:creator>関口宏司</dc:creator>
    <dc:publisher>JUGEM</dc:publisher>
    <dc:rights>関口宏司</dc:rights>
<taxo:topics>
<rdf:Bag>
<rdf:li rdf:resource="http://jugem.jp/contents/theme.php?theme=12" />
</rdf:Bag>
</taxo:topics>
  </item>

  <item rdf:about="http://lucene.jugem.jp/?eid=357">
    <link>http://lucene.jugem.jp/?eid=357</link>
    <title>オーバーライド可能になったSimilarityのnorm値計算メソッド（3.1）</title>
    <description>https://issues.apache.org/jira/browse/LUCENE-1260

アプリケーションによってはフィールドのnorm値計算（１バイトへのエンコード、１バイトからのデコード）をコントロールしたいという要望に応え、Similarityのstaticメソッドがdepracatedとなり、同じ機能を持つイ...</description>
<content:encoded><![CDATA[
<a href="https://issues.apache.org/jira/browse/LUCENE-1260" target="_blank">https://issues.apache.org/jira/browse/LUCENE-1260</a><br /><br />

アプリケーションによってはフィールドのnorm値計算（１バイトへのエンコード、１バイトからのデコード）をコントロールしたいという要望に応え、<a href="http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/Similarity.java?p2=%2Flucene%2Fjava%2Ftrunk%2Fsrc%2Fjava%2Forg%2Fapache%2Flucene%2Fsearch%2FSimilarity.java&p1=%2Flucene%2Fjava%2Ftrunk%2Fsrc%2Fjava%2Forg%2Fapache%2Flucene%2Fsearch%2FSimilarity.java&r1=883852&r2=883851&pathrev=883852&view=diff&diff_format=h" target="_blank">Similarityのstaticメソッドがdepracatedとなり、同じ機能を持つインスタンスメソッドが追加された</a>。
]]></content:encoded>
    <dc:subject>Luceneクラス解説</dc:subject>
    <dc:date>2009-11-25T08:26:32+09:00</dc:date>
    <dc:creator>関口宏司</dc:creator>
    <dc:publisher>JUGEM</dc:publisher>
    <dc:rights>関口宏司</dc:rights>
<taxo:topics>
<rdf:Bag>
<rdf:li rdf:resource="http://jugem.jp/contents/theme.php?theme=12" />
</rdf:Bag>
</taxo:topics>
  </item>

</rdf:RDF>