AWS SDK for PHPを使用したAmazon CloudSearchの設定及び検索方法

こんにちは。コンテンツメディア事業本部の鈴木です。

最近、Amazon CloudSearchについて調べています。

Amazon CloudSearchとは、AWS クラウドにおけるマネージド型サービスであり、ウェブサイトまたはアプリケーション向けの検索ソリューションを容易かつコスト効率良く設定、管理、スケールすることができるサービスです。

Amazon CloudSearchで検索ソリューションを構築する方法として、

  1. Amazon CloudSearch コンソール
  2. Amazon CLI
  3. AWS SDK

の3つの方法があります。

1と2を使用した構築方法は、開発者ガイドに丁寧に書かれているのですが、3については、

AWS SDKでは(Android および iOS SDK を除く)、Amazon CloudSearch設定APIで定義されたすべてのAmazon CloudSearchアクションがサポートされています。AWS SDKのインストールと使用の詳細については、「AWS Software Development Kits」を参照してください。

と、AWS Software Development Kitsから各AWS SDKドキュメントをお読みくださいとのこと。

今回AWS SDK for PHPを使用してAmazon CloudSearchにアクセスすることを考えていたため、AWS SDK for PHPを使用した設定及び検索方法について調べました。

Amazon CloudSearchの検索ソリューション構築手順

  1. 検索ドメイン作成
  2. インデックスフィールド設定
  3. データアップロード

※ 検索ドメインとは、RDBMSでいうテーブル
※ インデックスフィールドとは、RDBMSでいうカラム

環境

  • PHP 5.5.9
  • Amazon CloudSearch
    • インスタンスタイプ
      • search.m1.small
    • リージョン
      • Asia Pasific (Tokyo)

使用するデータ

事前準備

  • AWS SDK for PHPインストール
    • Composerでインストールしましょう
  • 検索ドメイン作成
    • AWS SDKからも作成できますが、アクセス設定があるのでAmazon CloudSearchコンソールで作成します
    • 今回は cloudsearch_test という検索ドメインを作っておきます
  • Amazon CloudSearchへアクセス可能なIAM
    • AWS SDKからアクセスするため ~/.aws/credential に追記しておきます
[cloudsearch]  
aws_access_key_id = XXXXXXXXXXX  
aws_secret_access_key = XXXXXXXXXXX  

事前準備が完了したらインデックスフィールドの設定をしていきます。

インデックスフィールド設定

今回は、郵便番号と住所の2つのインデックスフィールドを設定します。

<?php

require_once __DIR__ . '/vendor/autoload.php';

use Aws\CloudSearch\CloudSearchClient;
use Aws\Common\Enum\Region;

const DOMAIN_NAME = 'cloudsearch_test';

$client = CloudSearchClient::factory([
    'profile' => 'cloudsearch',
    'region'  => Region::AP_NORTHEAST_1 // Asia Pasific (Tokyo)
]);

// 郵便番号インデックスフィールドを設定
$client->defineIndexField([
    'DomainName' => DOMAIN_NAME,
    'IndexField' => [
        'IndexFieldName' => 'zipcode',
        'IndexFieldType' => 'int'
    ],
]);
// 住所インデックスフィールドを設定
$client->defineIndexField([
    'DomainName' => DOMAIN_NAME,
    'IndexField' => [
        'IndexFieldName' => 'address',
        'IndexFieldType' => 'text',
        'TextOptions' => [
            'AnalysisScheme' => '_ja_default_', // 日本語分析スキーム
            'HighlightEnabled' => true,         // フィールドにハイライトを返す
            'ReturnEnabled' => true,            // 検索結果でフィールドの内容を返す
            'SortEnabled' => true,              // フィールドを使用して検索結果をソートできる
        ],
    ],
]);

// ドキュメントのインデックス作成を開始
$result = $client->indexDocuments([
    'DomainName' => DOMAIN_NAME
]);

インデックスフィールドを設定するには、 defineIndexField関数を利用します。 ただし、インデックスフィールドを設定しただけではダメです。設定後必ず、 indexDocuments関数 を利用してインデックスを構築します。 構築には約10分ほどかかります。構築が完了したかを知りたい場合は、 describeIndexField関数で確認することができます。 StateActiveになれば構築完了です。 StateProcessingの場合は構築中なのでしばらく待ちましょう。

データアップロード

AWS SDKを使用してアップロードできる形式はJSONとXMLがあります。今回はJSON形式でアップロードします。 1度にアップロードできる容量は5MBまでです。今回利用するデータであれば1度でアップロードできます。

[
  {
    "type": "add",
    "id": 1,
    "fields": {
      "zipcode": "1020072",
      "address": "東京都千代田区飯田橋"
    }
  },
~~ 略 ~~
  {
    "type": "add",
    "id": 3750,
    "fields": {
      "zipcode": "1002211",
      "address": "東京都小笠原村母島"
    }
  }
]

では、上記のようなデータを用意してアップロードしてみます。

<?php

require_once __DIR__ . '/vendor/autoload.php';

use Aws\CloudSearch\CloudSearchClient;
use Aws\Common\Enum\Region;

const DOMAIN_NAME = 'cloudsearch_test';

$client = CloudSearchClient::factory([
    'profile' => 'cloudsearch',
    'region'  => Region::AP_NORTHEAST_1 // Asia Pasific (Tokyo)
]);

$domainClient = $client->getDomainClient(DOMAIN_NAME, [
    'credentials' => $client->getCredentials()
]);

// アップロードファイル読み込み
$updateDocuments = file_get_contents('アップロードファイル.json');

// ファイルアップロード
$result = $domainClient->uploadDocuments([
    'documents'   => $updateDocuments,
    'contentType' => 'application/json'
]);

これで検索の準備が整いましたので、検索してみましょう。

検索

addressフィールドに 渋谷区 を含むという条件で検索してみましょう

<?php

require_once __DIR__ . '/vendor/autoload.php';

use Aws\CloudSearch\CloudSearchClient;
use Aws\Common\Enum\Region;

const DOMAIN_NAME = 'cloudsearch_test';

$client = CloudSearchClient::factory([
    'profile' => 'cloudsearch',
    'region'  => Region::AP_NORTHEAST_1  // Asia Pasific (Tokyo)
]);

$domainClient = $client->getDomainClient(DOMAIN_NAME, [
    'credentials' => $client->getCredentials()
]);

// 検索
$result = $domainClient->search([
    'query'        => "(term field=address '渋谷区')",
    'queryParser'  => "structured",
    'highlight'    => "{address: {format:'text'}}",
    'return'       => "zipcode,address,_score",
    'size'         => 10
]);

// 検索結果表示
foreach ($result['hits']['hit'] as $hit) {
    printf("id=%s, zipcode=%s, address=%s, score=%s, highlight=%s\n",
        $hit['id'],
        $hit['fields']['zipcode'][0],
        $hit['fields']['address'][0],
        $hit['fields']['_score'][0],
        $hit['highlights']['address']
    );
}

検索結果

id=2570, zipcode=1500002, address=東京都渋谷区渋谷, score=6.31699, highlight=東京都*渋谷**区**渋谷*
id=2519, zipcode=1510064, address=東京都渋谷区上原, score=4.912977, highlight=東京都*渋谷**区*上原
id=2563, zipcode=1500021, address=東京都渋谷区恵比寿西, score=4.912977, highlight=東京都*渋谷**区*恵比寿西
id=2568, zipcode=1510073, address=東京都渋谷区笹塚, score=4.912977, highlight=東京都*渋谷**区*笹塚
id=2571, zipcode=1500046, address=東京都渋谷区松濤, score=4.912977, highlight=東京都*渋谷**区*松濤
id=2574, zipcode=1500041, address=東京都渋谷区神南, score=4.912977, highlight=東京都*渋谷**区*神南
id=2575, zipcode=1510051, address=東京都渋谷区千駄ヶ谷, score=4.912977, highlight=東京都*渋谷**区*千駄ヶ谷
id=2577, zipcode=1500043, address=東京都渋谷区道玄坂, score=4.912977, highlight=東京都*渋谷**区*道玄坂
id=2580, zipcode=1510066, address=東京都渋谷区西原, score=4.912977, highlight=東京都*渋谷**区*西原
id=2583, zipcode=1510061, address=東京都渋谷区初台, score=4.912977, highlight=東京都*渋谷**区*初台

検索には、search関数を利用します。

検索クエリですが、

// 検索
$result = $domainClient->search([
    'query'        => '(term field=address "渋谷区")', // ダブルクォーテーションで囲っています
    'queryParser'  => "structured",
    'highlight'    => "{address: {format:'text'}}",
    'return'       => "zipcode,address,_score",
    'size'         => 10
]);

では、エラーとなりました。。。違いは 渋谷区 をシングルクォーテーションではなくダブルクォーテーションで囲っているからです。

検索クエリの書き方については、Amazon CloudSearch によるデータの検索Amazon CloudSearch の検索 API リファレンスを読んでください。

まとめ

今回は基本設定について書かせていただきました。より詳細な設定(分析スキーム、ユーザ辞書登録、サジェスタetc..)についてもAWS SDKから設定可能です。詳しくは、ドキュメントをお読みください。