web-dev-qa-db-ja.com

Solrの部分文字列と完全文字列の一致

私はSolrで部分文字列の検索を許可しようとしています。そのため、誰かが「ppopota」を検索した場合、「hippopotamus」を検索した場合と同じ結果が得られます。ドキュメントを上下に読み、オプションを使い果たしたように感じます。これまでのところ、私は次のとおりです。

新しいフィールドタイプの定義:

<fieldtype name="testedgengrams" class="solr.TextField">
   <analyzer>
     <tokenizer class="solr.LowerCaseTokenizerFactory"/>
     <filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="15" side="front"/>
  </analyzer>
</fieldtype>

タイプ「testedgengrams」のフィールドの定義:

<field name="text_ngrams" type="testedgengrams" indexed="true" stored="false"/>

Text_ngramsの内容をテキストにコピー:

<copyField source="text_ngrams" dest="text"/>

悲しいかな、それはうまくいきません。何が欠けていますか?

23
Scripthead

EdgeNGramFilterFactory を使用しているため、「hi」、「hip」、「hipp」などのトークンが生成されるため、「ppopota」とは一致しません。代わりにNGramFilterFactoryを使用してください。

18

部分的な単語検索を有効にするには

通常はsolr/configの下にあるローカルschema.xmlファイルを編集して、次のいずれかを追加する必要があります。

  1. NGramFilterFactory
  2. EdgeNGramFilterFactory

これは私のものです: sample solr schema.xml

貼り付ける行は次のとおりです。

<filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="15" side="front"/>

EdgeNGram

EdgeNオプションを使用しました。単語の途中で検索することはできませんが、単語の先頭から始まる部分的な単語検索はできます。これにより、不要な誤検出/一致を大幅に削減し、パフォーマンスが向上し、通常ユーザーが見逃すことはありません。また、minGramSize = 2が好きなので、2文字以上入力する必要があります。一部の人々はこれを3に設定しました。

ローカルがセットアップされて機能したら、websolrが使用するschema.xmlを編集する必要があります。そうしないと、モデルに全文検索を設定している場合でも、フルワードを入力する必要があるデフォルトの動作になります。

次のレベルに進みます

インデックス作成を高速化する5つの方法

Herokuを使用している場合にwebsolr schema.xmlを編集するための特別な手順

  1. アプリのHerokuオンラインダッシュボードに移動します
  2. [リソース]タブに移動し、Websolrアドオンをクリックします
  3. [インデックス]の下のデフォルトのリンクをクリックします
  4. [詳細構成]リンクをクリックします
  5. 選択したNgramトークナイザーの構成を含めて、ローカルのschema.xmlに貼り付けます(上記を参照)。保存する。
  6. [Herokuアプリケーションの設定]ボックスのリンクをコピーし、ターミナルに貼り付けて、heroku設定にWEBSOLR_URLリンクを設定します。
  7. [インデックスステータス]リンクをクリックして気の利いた統計を取得し、高速か低速かを確認します。
  8. すべてのインデックスを再作成

herokuは、レーキの黒点を実行します:reindex [5000]

  • Heroku run rake sunspot:solr:reindexを使用しないでください-これは非推奨であり、パラメーターを受け入れず、速度がかなり遅いです
  • デフォルトのバッチサイズは50で、ほとんどの人は1000を使用することを推奨していますが、最大で5000以上に増やすと、結果が大幅に速くなります(約500 rpsではなく、1秒あたり1000行)。
11
Aaron Henderson

わかりました、フィールド名で同じことをしています

name_de

そして、私はこのようなcopyFieldを使用してこれをうまく機能させることができました:

schema.xml

<schema name="solr-magento" version="1.2">
    <types>
       ...
        <fieldType name="type_name_de_partial" class="solr.TextField">
            <analyzer type="index">
                <tokenizer class="solr.WhitespaceTokenizerFactory"/>
                <filter class="solr.NGramFilterFactory" minGramSize="3" maxGramSize="1000" side="front" />
                <filter class="solr.NGramFilterFactory" minGramSize="3" maxGramSize="1000" side="back" />
                <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true"/>
                <filter class="solr.LowerCaseFilterFactory"/>
                <filter class="solr.TrimFilterFactory" />
                <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
                <filter class="solr.SnowballPorterFilterFactory" language="German" protected="protwords_de.txt"/>
            </analyzer>
            <analyzer type="query">
                <tokenizer class="solr.StandardTokenizerFactory"/>
                <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
                <filter class="solr.LowerCaseFilterFactory"/>
                <filter class="solr.TrimFilterFactory" />
                <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
                <filter class="solr.SnowballPorterFilterFactory" language="German" protected="protwords_de.txt"/>
            </analyzer>
        </fieldType>
    </types>

    ...

    <fields>
        ...
        <field name="name_de_partial" type="type_name_de_partial" indexed="true" stored="true"/>
    </fields>

    ....

    <copyField source="name_de" dest="name_de_partial" />
</schema>

次に、solrconfig.xmlに検索条件を作成します

<requestHandler name="magento_de" class="solr.SearchHandler">
    <lst name="defaults">
        <str name="defType">dismax</str>
        <str name="echoParams">explicit</str>
        <str name="tie">0.01</str>                                          <!-- Tie breaker -->
        <str name="qf">name_de_partial^1.0 name_de^3.0</str>                <!-- Phrase Fields -->
        <str name="pf">name_de_partial^1.0 name_de^3.0</str>                <!-- Phrase Fields -->
        <str name="mm">3&lt;90%</str>                                       <!-- Minimum 'Should' Match [id 1..3 must much all, else 90proc] -->
        <int name="ps">100</int>                                            <!-- Phrase Slop -->
        <str name="q.alt">*:*</str>
        ..
    </lst>
    <arr name="last-components">
        <str>spellcheck</str>
    </arr>
</requestHandler>

この場合、solrは、pow 1.0ではフィールドname_de_partial、pow 3.0ではname_deを検索します。

したがって、エンジンがname_deで特定のクエリWordを見つけた場合、それはリストの一番上に置かれます。彼がname_de_partialでも何かを見つけた場合、それもカウントされ、結果に入れられます。

また、フィールドname_de_partialは特定のsolrフィルターを使用しているため、クエリ「hip」または「ppie」または「ippi」を使用して単語「hippie」を検索できます。

9
wormhit

EdgeNGramFilterFactoryまたはNGramFilterFactoryをインデックスとクエリの両方で設定し、q.op = AND(または、dismaxを使用している場合はデフォルトのmm = 100%)と組み合わせると、いくつかの問題が発生します。

インデックス時にのみNGramFilterFactoryを定義してみてください:

<fieldType name="testedgengrams" class="solr.TextField">
    <analyzer type="index">
        <tokenizer class="solr.LowerCaseTokenizerFactory"/>
        <filter class="solr.NGramFilterFactory" minGramSize="3" maxGramSize="15"/>
    </analyzer>
    <analyzer type="query">
        <tokenizer class="solr.LowerCaseTokenizerFactory"/>
    </analyzer>
</fieldType>

またはq.op = ORを設定してみてください(またはdismaxを使用している場合はmm = 1)

6
Andre85