<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<!-- EN-Revision: 24249 -->
<sect1 id="zend.search.lucene.query-language">
    <title>クエリ言語</title>

    <para>
        Java Lucene および <classname>Zend_Search_Lucene</classname> では、非常に強力なクエリ言語を使用できます。
    </para>

    <para>
        これらの言語はほぼ同じものですが、微妙に異なる点もあります。
        異なる点については以下で説明します。
    </para>

    <para>
        Java Lucene のクエリ言語の文法についての完全な文書は
        <ulink url="http://lucene.apache.org/java/2_3_0/queryparsersyntax.html">ここ</ulink>
        にあります。
    </para>

    <sect2 id="zend.search.lucene.query-language.terms">
        <title>用語</title>

        <para>
            クエリは、単語と演算子から成り立ちます。単語には三種類の形式があります。
            単一の単語、フレーズ、そしてサブクエリです。
        </para>
        <para>
            単一の単語とは、"test" や "hello" のようなひとつの単語です。
        </para>
        <para>
            フレーズとは、ダブルクォートで囲まれた複数の単語のグループ、たとえば
            "hello dolly" です。
        </para>
        <para>
            サブクエリとは、括弧で囲まれたクエリ、たとえば "(hello dolly)" です。
        </para>
        <para>
            複数の単語を論理演算子で組み合わせることで、より複雑なクエリを作成できます
            (以下を参照ください)。
        </para>
    </sect2>

    <sect2 id="zend.search.lucene.query-language.fields">
        <title>フィールド</title>

        <para>
            Lucene は、フィールド指定したデータをサポートしています。
            検索を行う際には、クエリを指定することもできますし、
            デフォルトのフィールドを使用することもできます。
            フィールド名はインデックス化されたデータに依存します。また、
            デフォルトのフィールドは現在の設定によって決まります。
        </para>
        <para>
            Java Lucene との最初の (そしてもっとも大きな) 違いは、デフォルトでは
            <emphasis>すべてのフィールド</emphasis> が検索の対象になるということです。
        </para>
        <para>
            <classname>Zend_Search_Lucene</classname> クラスにはふたつの静的メソッドがあり、
            この設定を操作できます。
        </para>

        <programlisting language="php"><![CDATA[
$defaultSearchField = Zend_Search_Lucene::getDefaultSearchField();
...
Zend_Search_Lucene::setDefaultSearchField('contents');
]]></programlisting>

        <para>
            <constant>NULL</constant> 値は、すべてのフィールドを検索の対象とすることを意味します。
            これがデフォルトの設定です。
        </para>
        <para>
            特定のフィールドを検索するには、まずフィールド名をタイプし、その後にコロン ":"
            を続け、探したい単語を指定します。
        </para>
        <para>
            例を見てみましょう。Lucene インデックスにはふたつのフィールド
            title および text があり、text がデフォルトのフィールドであるとします。
            タイトルが "The Right Way" で本文に "don't go this way"
            が含まれるドキュメントを探したいなら、
        </para>

        <programlisting language="querystring"><![CDATA[
title:"The Right Way" AND text:go
]]></programlisting>

        <para>
            あるいは下記にします。
            "text" はデフォルトのフィールドなので、フィールドの指定は必須ではなくなります。
        </para>

        <programlisting language="querystring"><![CDATA[
title:"Do it right" AND go
]]></programlisting>

        <para>
            注意: フィールドが有効なのは、その直後にある単語、
            フレーズあるいはサブクエリだけであることに注意しましょう。つまり、下記のクエリ
            は "Do" だけを title フィールドから探し、"it" や "right"
            はデフォルトのフィールドから探します。デフォルトのフィールドが
            <constant>NULL</constant> に設定されている場合は、"it" や "right"
            はすべてのフィールドから探します。
        </para>

        <programlisting language="querystring"><![CDATA[
title:Do it right
]]></programlisting>
    </sect2>

    <sect2 id="zend.search.lucene.query-language.wildcard">
        <title>ワイルドカード</title>
        <para>
            Lucene は、単一の文字あるいは複数の文字を表すワイルドカードをサポートしています
            これは、単語検索でのみ使用可能です (フレーズクエリでは使用できません)。
        </para>

        <para>
            単一の文字を表すワイルドカードは "?" です。
        </para>

        <para>
            複数の文字を表すワイルドカードは "*" です。
        </para>

        <para>
            単一文字のワイルドカードは、
            単語の中の "?" を別の一文字に置き換えたものにマッチする単語を探します。
            たとえば、"text" あるいは "test" を探したい場合はこうします。
        </para>

        <programlisting language="querystring"><![CDATA[
te?t
]]></programlisting>

        <para>
            複数文字のワイルドカードは、0 個以上の任意の数の文字に対応します。
            たとえば test、tests あるいは tester を探したい場合はこうします。
        </para>

        <programlisting language="querystring"><![CDATA[
test*
]]></programlisting>

        <para>
            "?" や "*" は単語のどの部分でも使え、
            また両方を同時に使うこともできます。たとえば
            下記は、"write" や "wrote"、"written"、"rewrite"、"rewrote" などに対応します。
        </para>

        <programlisting language="querystring"><![CDATA[
*wr?t*
]]></programlisting>

        <para>
            ZF 1.7.7 以降、ワイルドカードパターンにはワイルドカード以外のプレフィックスが必要となりました。
            デフォルトのプレフィックスの長さは 3 (Java Lucene と同じ) です。
            つまり "*", "te?t", "*wr?t*" といった単語は例外を引き起こします<footnote>
            <para>この例外は <classname>Zend_Search_Lucene_Search_QueryParserException</classname> ではなく
            <classname>Zend_Search_Lucene_Exception</classname> となることに注意しましょう。
            この例外がスローされるのは、クエリの書き換え (実行) 操作のときです。</para></footnote>。
        </para>
        <para>
            これは、<methodname>Zend_Search_Lucene_Search_Query_Wildcard::getMinPrefixLength()</methodname> および
            <methodname>Zend_Search_Lucene_Search_Query_Wildcard::setMinPrefixLength()</methodname>
            メソッドで変更できます。
        </para>
    </sect2>

    <sect2 id="zend.search.lucene.query-language.modifiers">
        <title>単語の修正子</title>

        <para>
            Lucene は、クエリの単語を修飾して幅広い検索オプションを指定することをサポートしています。
        </para>
        <para>
            "~" 修正子を使用すると、
            フレーズに対する近接検索や個別の単語に対するあいまい検索が可能となります。
        </para>
    </sect2>

    <sect2 id="zend.search.lucene.query-language.range">
        <title>範囲検索</title>

        <para>
            範囲検索は、フィールドの値の下限と上限を指定して
            その範囲に含まれるドキュメントを探すものです。
            最大値と最小値そのものを含めることも含めないこともできます。
            並べ替えは、辞書順で行われます。
        </para>

        <programlisting language="querystring"><![CDATA[
mod_date:[20020101 TO 20030101]
]]></programlisting>

        <para>
            これは、mod_date フィールドの値が 20020101 から 20030101 (両端を含む)
            であるドキュメントを探します。
            範囲検索は、日付フィールド以外でも使えることに注意しましょう。
        </para>

        <programlisting language="querystring"><![CDATA[
title:{Aida TO Carmen}
]]></programlisting>

        <para>
            これは、タイトルが Aida から Carmen までの間にあるドキュメントを探します。
            ただし、Aida および Carmen は含めません。
        </para>

        <para>
            両端の値を含めるには角括弧 []、含めない場合は波括弧 {}
            でクエリを指定します。
        </para>

        <para>
            フィールドを指定しなかった場合は、<classname>Zend_Search_Lucene</classname>
            はすべてのフィールドに対して範囲検索を行います。
        </para>

        <programlisting language="querystring"><![CDATA[
{Aida TO Carmen}
]]></programlisting>
    </sect2>

    <sect2 id="zend.search.lucene.query-language.fuzzy">
        <title>あいまい検索</title>
        <para>
            <classname>Zend_Search_Lucene</classname> は、Java Lucene と同様にあいまい検索をサポートします。
            これは、レーベンシュタイン距離のアルゴリズムにもとづくものです。
            あいまい検索を行うには、チルダ記号 "~" を単語の最後に指定します。
            たとえば、"roam" と似たスペルの単語を探すには、次のようなあいまい検索を使用します。
        </para>

        <programlisting language="querystring"><![CDATA[
roam~
]]></programlisting>

        <para>
            この検索は、foam あるいは roams といった単語にマッチします。
            (オプションの) 追加のパラメータによって、
            あいまい検索の程度を指定できます。
            このパラメータの値は 0 から 1 までの間となり、
            1 に近づくほど、類似点が多い単語にのみマッチするようになります。
            たとえば次のように使用します。
        </para>

        <programlisting language="querystring"><![CDATA[
roam~0.8
]]></programlisting>

        <para>
            このパラメータを省略した場合のデフォルトは 0.5 です。
        </para>
    </sect2>

    <sect2 id="zend.search.lucene.query-language.matched-terms-limitations">
        <title>マッチする単語の制限</title>

        <para>
            ワイルドカード検索や範囲検索、あいまい検索は、マッチする単語が多くなりすぎる可能性があります。
            そんな場合は検索のパフォーマンスが大幅に低下してしまいます。
        </para>

        <para>
            そこで、<classname>Zend_Search_Lucene</classname> はマッチする単語数の制限をクエリ (サブクエリ) 単位で設定します。
            この制限を取得したり設定したりするには
            <methodname>Zend_Search_Lucene::getTermsPerQueryLimit()</methodname>
            および <methodname>Zend_Search_Lucene::setTermsPerQueryLimit($limit)</methodname>
            メソッドを使用します。
        </para>
        <para>
            デフォルトのマッチ数の制限は、クエリ単位で 1024 です。
        </para>
    </sect2>

    <sect2 id="zend.search.lucene.query-language.proximity-search">
        <title>近接検索</title>

        <para>
            Lucene は、複数の単語が指定した範囲内にあらわれる状態の検索をサポートしています。
            近接検索を行うには、チルダ記号 "~" をフレーズの最後に指定します。
            たとえば、"Zend" と "Framework" がお互い 10 ワードの範囲内にあらわれるドキュメントを検索するにはこうします。
        </para>

        <programlisting language="querystring"><![CDATA[
"Zend Framework"~10
]]></programlisting>
    </sect2>

    <sect2 id="zend.search.lucene.query-language.boosting">
        <title>単語の強調</title>

        <para>
            Java Lucene および <classname>Zend_Search_Lucene</classname> は、
            見つかった単語にもとづいてドキュメントの関連度を提供します。
            ある単語の関連性を高くするには、キャレット記号 "^" に強調度 (数値)
            をあわせたものを、検索する単語の最後につなげます。
            強調度を高くするほど、その単語の関連性が高くなります。
        </para>
        <para>
            この機能を使用すると、単語の強調度によってドキュメントの関連性を制御できるようになります。
            たとえば
        </para>

        <programlisting language="querystring"><![CDATA[
PHP framework
]]></programlisting>

        <para>
            を検索しようとしており、単語 "PHP" をより重視したいとしましょう。
            そんな場合は ^ 記号と強調度を単語の後に続けます。つまり
        </para>

        <programlisting language="querystring"><![CDATA[
PHP^4 framework
]]></programlisting>

        <para>
            のようにします。これにより、 <acronym>PHP</acronym> という単語を含むドキュメントがより重視されるようになります。
            フレーズやサブクエリを強調することも可能です。たとえば
        </para>

        <programlisting language="querystring"><![CDATA[
"PHP framework"^4 "Zend Framework"
]]></programlisting>

        <para>
            のようになります。デフォルトの強調度は 1 です。強調度には正の数値を指定しますが、
            1 より小さくする (たとえば 0.2 など) ことも可能です。
        </para>
    </sect2>

    <sect2 id="zend.search.lucene.query-language.boolean">
        <title>論理演算子</title>

        <para>
            論理演算子によって、複数の単語を組み合わせることができます。
            Lucene では、論理演算子として AND、"+"、OR、NOT および "-"
            をサポートしています。Java Lucene では論理演算子をすべて大文字にする必要がありますが、
            <classname>Zend_Search_Lucene</classname> ではその必要はありません。
        </para>

        <para>
            論理クエリを作成するための方式は、大きく AND、OR および NOT の組と "+"、"-"
            の組に分けられます。Java Lucene とは異なり、<classname>Zend_Search_Lucene</classname>
            ではこれらの二つの組を混ぜて使うことはできません。
        </para>
        <para>
            AND/OR/NOT 形式を使用する場合は、AND/OR 演算子がすべてのクエリ単語の間に存在する必要があります。
            各単語の前には NOT 演算子をつけることができます。AND 演算子の優先順位は OR
            より高くなります。これは Java Lucene の挙動とは異なります。
        </para>

        <sect3 id="zend.search.lucene.query-language.boolean.and">
            <title>AND</title>
            <para>
                AND 演算子の意味は、"AND グループ"
                のすべての単語がドキュメントにマッチしなければならないということです。
            </para>
            <para>
                "PHP framework" および "Zend Framework" を含むドキュメントを検索するには
                下記を使用します。
            </para>

            <programlisting language="querystring"><![CDATA[
"PHP framework" AND "Zend Framework"
]]></programlisting>
        </sect3>

        <sect3 id="zend.search.lucene.query-language.boolean.or">
            <title>OR</title>
            <para>
                OR 演算子は、クエリをいくつかのオプションに分割します。
            </para>
            <para>
                "PHP framework" あるいは "Zend Framework" を含むドキュメントを検索するには
                下記を使用します。
            </para>

            <programlisting language="querystring"><![CDATA[
"PHP framework" OR "Zend Framework"
]]></programlisting>
        </sect3>

        <sect3 id="zend.search.lucene.query-language.boolean.not">
            <title>NOT</title>
            <para>
                NOT 演算子は、NOT の後に続く単語を含むドキュメントを除外します。
                しかし "AND グループ" が NOT 演算子つきの単語しか含まない場合は、
                インデックス化されたドキュメント全体ではなく空の結果を返します。
            </para>
            <para>
                "PHP framework" を含むけれども "Zend Framework" を含まないドキュメントを検索するには
                下記を使用します。
            </para>

            <programlisting language="querystring"><![CDATA[
"PHP framework" AND NOT "Zend Framework"
]]></programlisting>
        </sect3>

        <sect3 id="zend.search.lucene.query-language.boolean.other-form">
            <title>&amp;&amp;、|| および ! 演算子</title>
            <para>
                &amp;&amp;、|| および ! は、それぞれ AND、OR および NOT 演算子の代わりに使用します。
            </para>
        </sect3>

        <sect3 id="zend.search.lucene.query-language.boolean.plus">
            <title>+</title>
            <para>
                "+" 演算子 (必須演算子) は、
                "+" 記号の後の単語が必ずドキュメントにマッチしなければならないことを意味します。
            </para>
            <para>
                "Zend" を必ず含み、"Framework" を含んでも含まなくてもかまわないドキュメントを検索するには
                下記を使用します。
            </para>

            <programlisting language="querystring"><![CDATA[
+Zend Framework
]]></programlisting>
        </sect3>

        <sect3 id="zend.search.lucene.query-language.boolean.minus">
            <title>-</title>
            <para>
                "-" 演算子 (禁止演算子) は、
                "-" 記号の後の単語を含むドキュメントを検索結果から除外します。
            </para>
            <para>
                "PHP framework" を含むけれども "Zend Framework" を含まないドキュメントを検索するには
                下記を使用します。
            </para>
                <programlisting language="querystring"><![CDATA[
"PHP framework" -"Zend Framework"
]]></programlisting>
        </sect3>

        <sect3 id="zend.search.lucene.query-language.boolean.no-operator">
            <title>演算子なし</title>
            <para>
                演算子を使用しなかった場合は、
                その挙動は "デフォルトの boolean 演算子" として定義されます。
            </para>
            <para>
                これは、デフォルトでは 'OR' となります。
            </para>
            <para>
                つまり、その単語は任意となるということです。
                その単語はドキュメント中に存在するかもしれないし、しないかもしれません。
                ただ、その単語を含むドキュメントのほうが高いスコアとなります。
            </para>
            <para>
                "PHP framework" は必須で "Zend Framework" は含んでも含まなくてもかまわないドキュメントを検索するには
                下記を使用します。
            </para>

            <programlisting language="querystring"><![CDATA[
+"PHP framework" "Zend Framework"
]]></programlisting>

            <para>
                デフォルトの boolean 演算子を設定したり取得したりするには、それぞれ
                <classname>Zend_Search_Lucene_Search_QueryParser::setDefaultOperator($operator)</classname> および
                <classname>Zend_Search_Lucene_Search_QueryParser::getDefaultOperator()</classname> を使用します。
            </para>
            <para>
                これらのメソッドで使用する定数は、
                <classname>Zend_Search_Lucene_Search_QueryParser::B_AND</classname> および
                <classname>Zend_Search_Lucene_Search_QueryParser::B_OR</classname> です。
            </para>
        </sect3>
    </sect2>

    <sect2 id="zend.search.lucene.query-language.grouping">
        <title>グループ化</title>

        <para>
            Java Lucene および <classname>Zend_Search_Lucene</classname> では、
            括弧を使用して条件をグループ化することによるサブクエリの作成をサポートしています。
            これは、クエリのロジックを制御したい場合や異なるスタイルの論理クエリを共用したい場合などに便利です。
        </para>

        <programlisting language="querystring"><![CDATA[
+(framework OR library) +php
]]></programlisting>

        <para>
            <classname>Zend_Search_Lucene</classname> は、あらゆるレベルのサブクエリをサポートしています。
        </para>
    </sect2>

    <sect2 id="zend.search.lucene.query-language.field-grouping">
        <title>フィールドのグループ化</title>

        <para>
            Lucene では、括弧を使用して複数の条件をひとつのフィールドに適用できます。
        </para>
        <para>
            タイトルに単語 "return" とフレーズ "pink panther" の両方を含むドキュメントを検索するには
            下記を使用します。Zend_Search_Lucene は、あらゆるレベルのサブクエリをサポートしています。
        </para>

        <programlisting language="querystring"><![CDATA[
title:(+return +"pink panther")
]]></programlisting>
    </sect2>

    <sect2 id="zend.search.lucene.query-language.escaping">
        <title>特殊文字のエスケープ</title>

        <para>
            Lucene は、クエリの文法に含まれる特殊文字のエスケープをサポートしています。
            特殊文字に含まれるの文字は次のとおりです。
        </para>
        <para>
            + - &amp;&amp; || ! ( ) { } [ ] ^ " ~ * ? : \
        </para>
        <para>
            + および - が単一の単語の中に含まれる場合は、通常の文字として扱われます。
        </para>
        <para>
            これらの文字をエスケープするには、その文字の前に \ をつけます。
            たとえば、(1+1):2 を検索するには下記を使用します。
        </para>

        <programlisting language="querystring"><![CDATA[
\(1\+1\)\:2
]]></programlisting>
    </sect2>
</sect1>
