この記事では、PHPを使用してElasticsearch 7.xに接続し、データをインデックス化および検索する方法について説明します。
必要な環境は以下の通りです。
- Laravel 8
- PHP 7.3.4
- MySQL 5.7
- CentOS 8
Elasticsearchのクライアントをインストールします。
composer require elasticsearch/elasticsearch
インデックスを作成するためのパラメータ例です。
$settings = [
'index' => '和歌データベース', // インデックス名(MySQLのデータベースに相当)
'body' => [
'settings' => [
'number_of_shards' => 3, // シャード数
],
'mappings' => [
'properties' => [ // プロパティ設定(MySQLのカラムに相当)
'作者' => [
'type' => 'text',
'store' => true,
],
'本文' => [
'type' => 'text',
],
'タイトル' => [
'type' => 'keyword',
]
]
]
]
];
テスト用データとして「chinese-poetry」リポジトリを使用します。
Chinese Poetry GitHub Repository
MySQLのテーブル作成スクリプト。
CREATE TABLE `詩人` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`作者` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
`本文` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
`タイトル` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=290 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
簡体字と繁体字の変換には次のツールを使用します。
HanziConvert GitHub Repository
// 簡体字から繁体字への変換
$str = "好難";
HanziConvert::convert($str, true);
// 繁体字から簡体字への変換
$str = "好難";
HanziConvert::convert($str);
JSONデータを読み込み、MySQLに挿入するスクリプト。
$dataContent = file_get_contents('./poet.song.0.json');
$parsedData = json_decode($dataContent, true);
if (!empty($parsedData)) {
foreach ($parsedData as $item) {
$PoetRecord = new Poet();
$PoetRecord->author = HanziConvert::convert($item['author']);
$PoetRecord->paragraphs = HanziConvert::convert(implode(',', $item['paragraphs']));
$PoetRecord->title = HanziConvert::convert($item['title']);
$PoetRecord->save();
}
}
Elasticsearchクライアントの初期化とデータのインデックス化。
$clientBuilder = \Elasticsearch\ClientBuilder::create();
$clientBuilder->setHosts(['192.168.3.15:9200']);
$client = $clientBuilder->build();
$poets = Poet::all()->toArray();
foreach ($poets as $record) {
$params = [
'index' => '古文インデックス',
'id' => '記録_' . $record['id'],
'body' => [
'id' => $record['id'],
'author' => $record['author'],
'paragraphs' => $record['paragraphs'],
'title' => $record['title'],
],
];
$response = $client->index($params);
}
$searchParams = [
'index' => '古文インデックス',
'body' => [
'query' => [
'match' => [
'paragraphs' => '未離',
],
],
],
];
$results = $client->search($searchParams);
print_r($results);
検索結果の例。
Array
(
[took] => 6
[timed_out] =>
[_shards] => Array
(
[total] => 1
[successful] => 1
[skipped] => 0
[failed] => 0
)
[hits] => Array
(
[total] => Array
(
[value] => 23
[relation] => eq
)
[max_score] => 9.34944
[hits] => Array
(
...
)
)
)