App Engineでの全文検索を今すぐ

もちろん、誰もがApp Engineに表示される全文検索を楽しみにしていますが、これまでのところロードマップにはありません。 ただし、GAE / Javaの場合、全文検索を今すぐ独自にねじ込むことができます。



驚くでしょうが、これはLuceneです。 いやいや、急いで失望して、ため息をついてはいけません。 App EngineデータストアでLuceneと友達になるのはおそらく5分ではありませんが、JDOを使用する場合は、開発中のcompass 2.3のcompass-project開発者が既にこれを行っています(現在はベータ版です)。

Compassは、JDOオブジェクトをインデックス付きドキュメントに変換し、それらを検索結果として返すことができます。 インデックス付けと検索を含む最も単純なJDOオブジェクトのコード、およびその中の興味深い場所に関するコメントは、以下を参照してください。 これをコンパイルして動作させるには、いくつかのライブラリをwar/WEB-INF/libに追加する必要があります: lucene-core, commons-logging compass-2.3.0-beta1 。 彼らは全員、コンパスの夜間配布キットに住んでいます。これは、継続的なビルドシステムのジャングルの奥深くに埋められています。 執筆時点で、最後に成功したビルドはここにあります: http : //build.compass-project.org/download/CMPTRK-NIGHTLY/artifacts/build-786/Release この特定のビルドのパフォーマンスを確認しなかったことは認めます。

@PersistenceCapable(identityType = IdentityType.APPLICATION)
@Searchable // [1]
public class GreetingServiceUser {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
@SearchableId
private Long id; // [2]

@Persistent
private String name;

public GreetingServiceUser( String name) {
this .name = name;
}

@SearchableProperty // [3]
public String getName() {
return name;
}

private static final PersistenceManagerFactory factory =
JDOHelper.getPersistenceManagerFactory( "transactions-optional" );
private static Compass compass;
private static CompassGps compassGps;

static {
// [4]
compass = new CompassConfiguration()
.setConnection( "gae://index" )
// [5]
.setSetting(CompassEnvironment.ExecutorManager.EXECUTOR_MANAGER_TYPE,
"disabled" )
.addScan( "compass_test" )
.buildCompass();
compassGps = new SingleCompassGps(compass);
Jdo2GpsDevice jdo2GpsDevice = new Jdo2GpsDevice( "appengine" , factory);
// [6]
jdo2GpsDevice.setMirrorDataChanges( false );
compassGps.addGpsDevice(jdo2GpsDevice);
// [7]
// if (compass.getSearchEngineIndexManager().isLocked()) {
// compass.getSearchEngineIndexManager().releaseLocks();
// }
compassGps.start();
}

public void save() {
PersistenceManager pm = factory.getPersistenceManager();
CompassIndexSession indexSession = null ;
try {
pm.makePersistent( this );

// [8]
// compass.getSearchEngineIndexManager().releaseLocks();

// [9]
indexSession = compass.openIndexSession();
indexSession.save( this );
indexSession.commit();
}
catch (Throwable e) {
e.printStackTrace();
}
finally {
pm.close();
if (indexSession != null ) {
indexSession.close();
}
}
}

public static List <GreetingServiceUser> search( String query) {
CompassSearchSession searchSession = compass.openSearchSession();

CompassHits hits = searchSession.find(query);
List <GreetingServiceUser> results =
new ArrayList <GreetingServiceUser>(hits.getLength());
PersistenceManager pm = factory.getPersistenceManager();
try {
for ( int i=0; i<hits.length(); i++) {
// [10]
results.add(pm.getObjectById(
GreetingServiceUser. class ,
Long.valueOf(hits.resource(i).getId())));
}
}
catch (JDOObjectNotFoundException e) {
e.printStackTrace();
}
finally {
pm.close();
}
return results;
}
}

* This source code was highlighted with Source Code Highlighter .


[1]注釈は、インデックス付けされるJDOクラスを示します...
[2] ...ドキュメントを識別するプロパティ、...
[3] ...そして最後に、値がインデックス付けされるプロパティ。
[4] Compassインスタンスを構築するとき、そのような注釈を検索する際にスキャンするパッケージを指定します
[5]これはApp Engine固有の微妙な問題です。 通常、コンパスは複数のスレッドで実行されますが、App Engineでスレッドを作成できないため、スレッドを無効にする必要があります。
[6]これは、App Engineに関連する小さなハックでもあります。 コンパスは、興味深い持続データで何かが変更されたときに、インデックスを自動的に更新する方法を実際に知っています。 ただし、App Engineで作業する場合、割り当てられた30秒を満たしていない場合があります。 setMirrorDataChanges(false)を呼び出すと、自動更新が無効になり、インデックスを手動で更新する必要があります。 これは痛みを伴うものではなく、補償として、たとえばタスクキュー内の別のタスクで実行できます。
[7、8] App Engineのサポートはまだ弱く、コンパスはインデックスロックの解除を忘れているように見える場合があります。 私は理由と修正の正しい方法を理解していませんが、ロックを解除する明示的な要求が役立ちます。 もちろん、これはあまり安全ではないかもしれないことを理解する必要があります。 誰かが問題を見つけて倒す時間を見つけたら、私に知らせてください。
[9]実際には、オブジェクトは手動でインデックス付けされます。
[10]検索結果はCompassHitsコレクションです。 data(int)メソッドを使用して、見つかったオブジェクト(この例ではGreetingServiceUser )を抽出することは理論的には可能ですが、それらは空の値であることがわかりました。 したがって、ドキュメントに対応するResourceオブジェクトを使用し、そこからドキュメントIDを抽出し、JDO / AppEngineを使用して対応するJDOオブジェクトを探します。

Source: https://habr.com/ru/post/J90223/


All Articles