私のPlayframework-e Webプロジェクトの1つで、ある日、検索が必要になりました。 ランク付けやその他の「スマートな」検索グッズを望んでいたので、すぐにlikeを使用してデータベースを検索するというアイデアを却下しました。自転車を発明する時間も欲望もありませんでした。
Javaでのプロジェクト以来、これにLuceneを使用することは非常に魅力的でした。
Googleで、すぐに
SearchというPlayframeworkの素晴らしいモジュールを見つけました。また、Luceneを使用する
Elastic Searchモジュールを見つけましたが、別のサーバーのインストールが必要なため、フラグが付けられました。 検索モジュールはシンプルであるため気に入っています。その中のすべての「添えもの」はカプセル化されているため、使用は非常に簡単です。
モジュールのインストールでは、いつものようにPlay-eで問題はありませんでした
。playinstall searchコマンドはバタンと動作し、モジュールをリポジトリから送り出しました。
application.confにmodule.search = $ {play.path} /modules/search-2.0を追加することで、アプリケーションで既に使用できます。
短いチュートリアルに従って、実際に検索する必要がある
エントリエンティティ、
@ Indexedアノテーション、および
@Fieldアノテーションの説明フィールドに
追加しました 。
コントローラに次のコードを書くことにより:
public static void search(String phrase, int page) { int pageSize = PAGE_SIZE; Query query = Search.search("description:" + phrase, Entry.class); List<Entry> entries = query.page(page*pageSize, pageSize).fetch(); long totalCount = query.count(); render(entries, totalCount, page, pageSize, phrase); }
私はすでに最初のテストを実行して機能を向上させる準備ができていましたが、問題が始まりました...
検索は機能しませんでした。つまり、
count()メソッドは
0を返し、
エントリリストは空でした。 ロシア語と英語の両方で検索しようとし、
Search.rebuildAllIndexes()を呼び出し 、さらに多くのことを試みましたが、結果は変わりませんでした。
幸いなことに、play-eのモジュールはソースと一緒にダウンロードされ、バイアスされる可能性があります。 短いデバッグでは、
説明フィールドがインデックスに挿入されていないことが示されました。 少し深く
調べてみると、
@ Fieldアノテーションを検索する
際に、
object.getClass()メソッドがエンティティフィールドで使用されていることが
わかりました
。 getFields()が停止しますが、このメソッドはパブリックフィールドのみを返します。私の本質では、フィールドはアクセスを保護する必要があり、モジュール作成者は
getDeclaredFields()メソッドを使用する必要があり
ます 。
ここで余談にします。少なくとも「戦闘」サーバーでインストール検索を実行する機能を失うため、モジュールを再構築してその中のコードを変更したくはありませんでしたが、再構築されたモジュールに手を入れなければなりません。 バグレポートを書いたり、パッチを提供したりするのは簡単なことではありませんでしたが、今では機能が必要でした。一般的に、モジュールでこのバグが修正されるまで、
説明フィールドを公開し、todoを書くことが決定されました。 そして、見よ、検索が獲得しました!
チュートリアルを読んだ後、私がすでに推測した次の問題は、モジュールに「キラー機能」があったことです-エンティティのCRUD操作中にインデックスの自動更新(および新しいレコードの追加)—これは必要ありませんでした。 実際、システムに追加されたレコードは事前にモデレートされますが、検索に「モデレートされていない」レコードは絶対に必要ありません。
モデレート後に自分で
Search.index(エントリ)を呼び出したいです。 私は、ソースで構成内のいくつかの行のチェックを見つけることを本当に望んでいました:インデックスを自動的に更新するかしないか、SearchPluginコードで
これに遭遇
しました:
@Override public void onEvent(String message, Object context) { if (!message.startsWith("JPASupport")) return; if (message.equals("JPASupport.objectPersisted") || message.equals("JPASupport.objectUpdated")) { Search.index (context); } else if (message.equals("JPASupport.objectDeleted")) { Search.unIndex(context); } }
どうにかしてそれをオフにすることはできませんでした。パッチを送信し、修正されたバージョンをより早くリリースするためにキックすることを考える時が来たようです。これをlibフォルダーに入れました。
コードを掘り下げると、アプリケーションを起動するときに次のことを行う必要があることがわかりました。
Search.init(); FileExtractor.init();
そして、停止するとき:
try { Search.shutdown(); } catch (Exception e) { throw new UnexpectedException (e); }
これは、
@ OnApplicationStart / Stop注釈付きの
ジョブを使用して簡単に実行できます。
次のステップは、プラグインであると考えるためにプレイを離すことでした。
実際 、Playframeworkはplay.plugins
ファイルを使用してクラスパス内のモジュールを検索します。
実際 、通常のアーカイバーでは、このファイルはjarファイルから削除され、すべてが回転してねじれました。
私の経験が役立って、仕事でPlayframeworkを使用する人々の時間を節約することを願っています。
PS:モジュールをlibフォルダーに配置する必要があったため、パブリックフィールドのバグを修正してモジュールを再構築しました。 :)