■ Search Data Format (SDF)
Amazon CloudSearchでデータをインデクシングするのにSDFというフォーマット(JSONもしくはXML)で
データをアップロードする必要がありますが、2014年1月現在、以下の方法があります。
1. コマンドラインツールをインストールしてcs-import-documentsコマンドを使う
2. ManagementConsoleでブラウザからポチポチする
3. DocumentEndpointに直接curl等でPOSTする
SDFフォーマット的には↓に詳しく記載されていますが、
http://aws.amazon.com/articles/8871401284621700#_Ref198105621
以下のような情報が必要な感じになります。
– 操作種別(add/delete)
– 一意の識別子
– バージョン番号
– 言語コード(en)
– 実際のフィールドとデータ
■ SDKを使って開発しているのでその中でやりくりしたい
先日、Solrをイジっていて、SolrJでクライアントプログラミングしてみました(http://shinodogg.com/?p=5899)が、
ソレと同じようなノリで、Javaのオブジェクトを作って、そのままインデクシングしたいな、と。
■ まずはAmazon CloudSearchに検索サーバーを準備してSDKからアクセス
CloudSearchにDomainを定義します。
(後からtextフィールドもresultのチェック入れましたが、件数なくてもActiveになるまでそこそこ時間かかります)
JavaのSDKのCloudSearchなクラスを使ってアクセスしてみます。
– CloudSearchのクライアント。リージョンはVirginia(まだ日本にきてないので)
AmazonCloudSearchClient client = new AmazonCloudSearchClient(new PropertiesCredentials(SampleIndexer.class.getResourceAsStream("AwsCredentials.properties")));
client.setRegion(Region.getRegion(Regions.US_EAST_1));
– 検索ドメインを表示
↓この辺の情報が取れます。(複数ドメインがあれば複数)
・ドメインのID, 名前, 作成済み, 削除済み, 検索対象ドキュメント数
・ドキュメントサービス(インデクシング)のエンドポイント, サーチサービスのエンドポイント
・インスタンスのタイプや数、パーティション数なんかも
DescribeDomainsResult describeDomainsResult = client.describeDomains();
List domainStatusList = describeDomainsResult.getDomainStatusList();
for (DomainStatus status: domainStatusList) {
System.out.println(status);
}
– ドメインのフィールドを表示
DescribeIndexFieldsRequest describeIndexFieldsRequest = new DescribeIndexFieldsRequest();
describeIndexFieldsRequest.withDomainName("sample");
DescribeIndexFieldsResult indexFieldsResult = client.describeIndexFields(describeIndexFieldsRequest);
List indexFieldStatusList = indexFieldsResult.getIndexFields();
for (IndexFieldStatus idxFieldStatus : indexFieldStatusList) {
System.out.println(idxFieldStatus);
}
↓こんな感じでイロイロ取れます。いつそのフィールドのドメイン定義がUpdateされた〜とか。
{Options: {IndexFieldName: detail,IndexFieldType: text,TextOptions: {FacetEnabled: false,ResultEnabled: true,},SourceAttributes: []},Status: {CreationDate: Tue Jan 07 16:01:26 JST 2014,UpdateDate: Tue Jan 07 20:43:00 JST 2014,UpdateVersion: 22,State: Active,PendingDeletion: false}}
{Options: {IndexFieldName: head,IndexFieldType: text,TextOptions: {FacetEnabled: false,ResultEnabled: true,},SourceAttributes: []},Status: {CreationDate: Tue Jan 07 16:01:25 JST 2014,UpdateDate: Tue Jan 07 20:43:00 JST 2014,UpdateVersion: 22,State: Active,PendingDeletion: false}}
{Options: {IndexFieldName: id,IndexFieldType: uint,SourceAttributes: []},Status: {CreationDate: Tue Jan 07 16:01:23 JST 2014,UpdateDate: Tue Jan 07 16:31:16 JST 2014,UpdateVersion: 14,State: Active,PendingDeletion: false}}
んま、とりあえず、SDKを使ってCloudSearchと会話できる確認がとれましたよ、と。
■ JavaのオブジェクトからSDFを生成してPOSTする
SDFと言っても、普通のJSON(もしくはXML)なので、普通にバリューオブジェクトを作れば良さそうです。
ということで、まずはJavaなJSON用ライブラリ。
以前はよくJacksonというライブラリを使っていましたが、ググったらGoogleのがあるらしいので
(その名もGson。ストレートな名前がグッときますね。笑)、それを使ってみます。
↓pom.xmlに定義を追加してmavenでjarファイルをダウンロードしてきます。
<dependencies>
<!-- Gson: Java to Json conversion -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
<scope>compile</scope>
</dependency>
</dependencies>
– Valueオブジェクトを作ります。
・SDF
public class SDF {
private String type; //操作種別(add/delete)
private String id; //一意の識別子
private int version; //バージョン番号
private String lang; //言語コード(en)
private Sample fields; //実際のフィールドとデータ
〜 setterとgetterは省略 〜
・ドメインで定義したヤツ
public class Sample {
private int id;
private String head;
private String detail;
〜 setterとgetterは省略 〜
– ドカっと値を詰めてやります。
List<SDF> sdfList = new ArrayList<SDF>();
SDF sdf = new SDF();
sdf.setType("add");
sdf.setId("111111");
sdf.setVersion(1111);
sdf.setLang("en");
Sample sample = new Sample();
sample.setId(1111);
sample.setHead("sample head 11");
sample.setDetail("sample detail 12");
sdf.setFields(sample);
sdfList.add(sdf);
sdf = new SDF();
sdf.setType("add");
sdf.setId("111112");
sdf.setVersion(1111);
sdf.setLang("en");
sample = new Sample();
sample.setId(1112);
sample.setHead("head bungin");
sample.setDetail("detail junkie");
sdf.setFields(sample);
sdfList.add(sdf);
上記で2レコードを追加するJavaなオブジェクトが出来上がりました。
– オブジェクトをJSON文字列に。スッゲー簡単…。
Gson gson = new Gson(); System.out.println(gson.toJson(sdfList));
↓インデントするとこんな感じになります。
[
{
"fields": {
"detail": "sample detail 12",
"head": "sample head 11",
"id": 1111
},
"id": "111111",
"lang": "en",
"type": "add",
"version": 1111
},
{
"fields": {
"detail": "detail junkie",
"head": "head bungin",
"id": 1112
},
"id": "111112",
"lang": "en",
"type": "add",
"version": 1111
}
]
– よくあるHTTPクライアントなヤツ
HttpClient httpClient = new DefaultHttpClient();
// POSTでドキュメントエンドポイントに。
// URLの最後の方の"2011-02-01"はCloudSearchのバージョン名で今のところコレです。
HttpPost post = new HttpPost("http://doc-sample-xxx.us-east-1.cloudsearch.amazonaws.com/2011-02-01/documents/batch");
// JavaオブジェクトをJSONにしてContentTypeの設定&エンティティにセット
StringEntity entity = new StringEntity(gson.toJson(sdfList));
entity.setContentType("application/json");
post.setEntity(entity);
// 実行して結果を取得
HttpResponse response = httpClient.execute(post);
System.out.println(response.getStatusLine());
String responseString = EntityUtils.toString(response.getEntity());
System.out.println(responseString);
– 実行結果
ステータスコードと何件追加したよ的なヤツが返ってきます。
HTTP/1.1 200 OK
{"status": "success", "adds": 2, "deletes": 0}
■ ManagementConsoleからクエリ
↓正しくインデックスされていることが確認出来ました。
上記のコードも大量にデータを扱うとなるとイロイロとチューニングなポイントがありそうですが、
一般的なライブラリの組み合わせでやりくり出来そうです。
■ 次回は、、
SnapDishの清田さんのブログで形態素解析まわりをCloudSearchの外でやって、
日本語でもCloudSearchを活用されている例が紹介されていますが、
Yahoo!さんが日本語形態素解析APIを公開していたりするので、
そちらを使ってCloudSearchでの日本語の検索を試してみたいと思います。
技術評論社
売り上げランキング: 5,985
![[改訂新版] Apache Solr入門 ~オープンソース全文検索エンジン (Software Design plus)](http://ecx.images-amazon.com/images/I/51N38JQ9-SL._SL160_.jpg)


コメント