PHP 上 Elasticsearch 應用
What is Elasticsearch?
Elasticsearch 是一套基於 Apache Lucene(TM) 的開源搜尋引擎。無論在開源或專有禮遇,Lucene 被認為至今最先進、性能最好、功能最齊全的搜尋引擎。
不過 Elasticsearch 不僅僅是 Lucene 和全文搜尋,我們還能這樣去描述它:
- 分佈式的實時文進存儲,每個字段都被索引並可被搜尋。
- 分佈式的實時分析搜尋引擎。
- 可拓展至上百台服務器,處理PB級結構化或非結構化數據。
環境建置
第一步安裝 Elasticsearch 環境
Elasticsearch 安裝有需多不同方式(待補其他方式)。
此處筆者至 Elasticsearch官網 直接下載最新版並解壓縮使用。
此處筆者至 Elasticsearch官網 直接下載最新版並解壓縮使用。
檔案包安裝好後由CMD直接進入該專案包下指令喚醒 Elasticsearch
bin/elasticsearch
。
請注意喚醒 ES 不可使用 root 身份進行,並確認專案內部分檔案開放該身份存取(logs 等…)
如何確認 ES 是否安裝成功?
可直接使用網頁連結
可直接使用網頁連結
http://localhost:9200/
若出現畫面。{
"name" : "BSQmiuK",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "d6gTLQ0-Svy1WbTWSvKmig",
"version" : {
"number" : "6.2.4",
"build_hash" : "ccec39f",
"build_date" : "2018-04-12T20:37:28.497551Z",
"build_snapshot" : false,
"lucene_version" : "7.2.1",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
代表大致上沒有問題。
如何在 php 上應用 Elasticsearch?
筆者此處使用 composer 檔案管理套件進行ES-PHP檔案安裝。
若無此套件可先進行環境建置。
若無此套件可先進行環境建置。
PHP 上使用Elasticsearch
先在專案內新增
composer.json
檔並包含 elasticsearch-php
(筆者編寫時最新版本需配合 php7,固取得版本 5.0 配合 PHP 5.6)。
composer.json 檔內容
{
"require": {
"elasticsearch/elasticsearch": "~5.0"
}
}
完成後 cmd 到專案目錄下進行
composer install
進行套件安裝。
於專案內新增
index.php
,使用自動加載並實例化客戶端。require 'vendor/autoload.php';
use Elasticsearch\ClientBuilder;
$client = ClientBuilder::create()->build();
建立索引資歷。將以下 code 添加至 index.php
內
$params = [
'index' => 'my_index',
'type' => 'my_type',
'id' => 'my_id',
'body' => ['testField' => 'abc'],
];
$response = $client->index($params);
var_dump($response);
於網頁執行應該回得到頁面訊息
array (size=8)
'_index' => string 'my_index' (length=8)
'_type' => string 'my_type' (length=7)
'_id' => string 'my_id' (length=5)
'_version' => int 6
'result' => string 'updated' (length=7)
'_shards' =>
array (size=3)
'total' => int 2
'successful' => int 1
'failed' => int 0
'_seq_no' => int 5
'_primary_term' => int 1
返回 response 為 Elasticsearch 創建索引返回的 JSON 解碼關聯表。
依條件取得索引資料
$params = [
'index' => 'my_index',
'type' => 'my_type',
'id' => 'my_id',
];
$response = $client->get($params);
var_dump($response);
我們可以依照索引設置及 get 取得文檔資料
array (size=6)
'_index' => string 'my_index' (length=8)
'_type' => string 'my_type' (length=7)
'_id' => string 'my_id' (length=5)
'_version' => int 1
'found' => boolean true
'_source' =>
array (size=1)
'testField' => string 'abc' (length=3)
依索引刪除資料
$deleteParams = [
'index' => 'my_index',
];
$response = $client->indices()->delete($deleteParams);
print_r($response);
得到確認回應
Array ( [acknowledged] => 1 )
關鍵字搜尋
Elasticsearch 可對入稿之資料內容做比對搜尋。
關鍵字若下”後山大火雞”,那”後”、”山”、”大”、”火”、”雞”、”後山”、”火雞”(請自行依此類推)皆會成為搜尋條件並找出一定比重之資料。
讓我們來看看該怎麼做。
首先幫我入稿基本資料:
$params = [
'index' => 'my_index2',
'type' => 'my_type',
'body' => ['count' => '後山大火雞'],
];
$client->index($params);
$params = [
'index' => 'my_index',
'type' => 'my_type',
'body' => ['count' => '火雞'],
];
$client->index($params);
$params = [
'index' => 'my_index',
'type' => 'my_type',
'body' => ['count' => '後山'],
];
$client->index($params);
$params = [
'index' => 'my_index',
'type' => 'my_type',
'body' => ['count' => '後大'],
];
$client->index($params);
搜尋功能應用(其中僅入稿資料”後山” 不再搜尋關鍵字 “大火雞” 拆分比對資料內因故沒被顯示出來)。
$paramsSeach['body'] = array(
'query' => array(
'match' => array(
'count' => '大火雞',
),
)
);
$results = $client->search($paramsSeach);
var_dump($results['hits']['hits']);
上述指令會取得結果
array (size=3)
0 =>
array (size=5)
'_index' => string 'my_index' (length=8)
'_type' => string 'my_type' (length=7)
'_id' => string 'S2fIPmMBYbAZcmkxgr3x' (length=20)
'_score' => float 1.3862944
'_source' =>
array (size=1)
'count' => string '火雞' (length=6)
1 =>
array (size=5)
'_index' => string 'my_index2' (length=9)
'_type' => string 'my_type' (length=7)
'_id' => string 'SmfIPmMBYbAZcmkxgr2d' (length=20)
'_score' => float 0.8630463
'_source' =>
array (size=1)
'count' => string '後山大火雞' (length=15)
2 =>
array (size=5)
'_index' => string 'my_index' (length=8)
'_type' => string 'my_type' (length=7)
'_id' => string 'TWfIPmMBYbAZcmkxg70I' (length=20)
'_score' => float 0.2876821
'_source' =>
array (size=1)
'count' => string '後大' (length=6)
搜尋應用還可對指定索引進行搜尋,於上方資料
後山大火雞
可發現其陣列內 index
欄位與其他幾項不同。
此時只要添加索引條件:
$paramsSeach['index'] = 'my_index';
由於此處指定搜尋
index
,故會發現搜尋搜尋結果以濾掉 ['index' => 'my_index2']
的 後山大火雞
。————————————
以上為 Elasticsearch-php 基本應用。
其實有許多功能筆者皆未提到。
例: Elasticsearch 監聽程式(Elasticsearch-head)、或全域搜尋功能。還有許多分析功能。
其實有許多功能筆者皆未提到。
例: Elasticsearch 監聽程式(Elasticsearch-head)、或全域搜尋功能。還有許多分析功能。
待筆者日後對 Elasticsearch 掌握度更加精進後,在進行文件補充動作
————————————-
以下附上 DB 相關進階應用:
DB 與 ES 數據庫連結(conn.php)
<?php
require_once 'vendor/autoload.php';
//連結 MySql 資料庫
function get_conn()
{
@$conn = mysql_connect("localhost", "root", "root") or die("error connecting");
mysql_select_db("DBName", $conn); # *DB 請自行填入
mysql_query("SET NAMES 'UTF8'");
return $conn;
}
//由 DB 取得資料並回存ES中
function create_index($maxId, $client)
{
//取捯 DB 資料
$sql = "SELECT * FROM tableName where id > $maxId limit 0,300"; # *資料表名稱請自行填入
get_conn();
@$result_bugs = mysql_query($sql);
while (@$row = mysql_fetch_assoc(@$result_bugs)) {
$rtn[] = $row;
}
foreach ($rtn as $val) {
$params = array();
$params['body'] = array(
'id' => $val['id'],
'count' => $val['count'], # *請自行修改比對欄位及名稱
);
$params['index'] = 'index';
$params['type'] = 'title';
$client->index($params);
}
return (count($rtn) == 300) ? $val['id'] : false;
}
// set_time_limit(0);
$client = Elasticsearch\ClientBuilder::create()->setHosts(['localhost'])->build();
//刪除所有數據
// $client->indices()->delete(['index' => 'index']);
$a = true;
$maxId = 0;
while ($a) {
$maxId = create_index($maxId, $client);
if (empty($maxId)) {
$a = false;
}
}
執行php(testConn.php)
<?php
//引入 DB 連結
require 'conn.php';
require_once 'vendor/autoload.php';
function search($keyword, $page = 0, $size = 20)
{
//實體化對象
$client = Elasticsearch\ClientBuilder::create()->setHosts(['localhost'])->build();
//查詢數據庫拼裝
$params = array();
$params['index'] = 'index';
$params['type'] = 'title';
$params['body']['query']['match']['count'] = $keyword;
$params['from'] = $page;
$params['size'] = $size;
//查詢
$rtn = $client->search($params)['hits'];
//結果組裝
$data['total'] = $rtn['total'];
$data['lists'] = array_column($rtn['hits'], '_source');
$data['lists'] = formartData(array_column($data['lists'], 'id'));
return $data;
}
function formartData($ids)
{
$ids = implode($ids, ',');
$sql = "select * from articles where id in($ids)";
$data = mysql_query($sql);
$rtn = [];
while (@$row = mysql_fetch_assoc(@$data)) {
$rtn[] = $row;
}
return $rtn;
}
$q0 = isset($_GET['q']) ? $_GET['q'] : 'SQL注入';
$num = "15"; //每頁顯示比數
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
$offset = ($page - 1) * $num;
$esData = search($q0, $offset, $num);
var_dump($esData);
使用方式:呼叫程式並賦予搜尋值。
http://localhost/testConn.php?q=
- 注意1:
索引(index)
與型態(type)
設定時必須小寫。
聲明:此篇教學僅提供學習與交流使用,請勿用於商業用途。
留言
張貼留言