<?php
namespace app\service;
use Elasticsearch\ClientBuilder;
use app\service\Service;
class ElasticsearchService extends Service
{
private $client;
private $index_name;
private $type;
// 构造函数
public function __construct()
{
$elasticsearch_hosts = [];
$this->client = ClientBuilder::create()->setHosts($elasticsearch_hosts)->build();
$this->index_name = 'shuiguo'; // 索引名(项目名)
$this->type = '_doc'; // 类型
}
public static function build() {
return new self();
}
/**
* 删除索引
*
* @param string $keyName 索引名
* @return void
*/
public function deleteIndex(string $keyName)
{
$params = ['index' => $keyName];
return $this->client->indices()->delete($params);
}
/**
* 判断文档存在
* @param string $keyName 索引名
* @param string $id 索引id
* @return bool
*/
public function existsDoc(string $keyName, string $id)
{
$params = [
'index' => $this->index_name .'_'. $keyName,
'type' => $this->type,
'id' => $id
];
return $this->client->exists($params);
}
/**
* 添加文档(单条)
* @param string $keyName 索引名
* @param string $id 索引id
* @param array $doc 跟创建文档结构时properties(es文档模板)的字段一致
* @return array|callable
*/
public function addDoc(string $keyName, string $id, array $doc)
{
$params = [
'index' => $this->index_name .'_'. $keyName,
'type' => $this->type,
'id' => $id,
'body' => $doc
];
return $this->client->index($params);
}
/**
* 添加文档(批量),如果id已存在则为更新
* @param string $keyName 索引名
* @param string $id 索引id
* @param array $list 跟创建文档结构时properties(es文档模板)的字段一致
* @return array|callable
*/
public function addDocAll(string $keyName, array $list)
{
$index_name = $this->index_name .'_'. $keyName;
$docs = [];
foreach ($list as $key => $value) {
$docs['body'][] = ['index'=>['_index'=>$index_name, '_id'=>$value['id']]];
$docs['body'][] = $value;
}
return $response = $this->client->bulk($docs);
}
/**
* 删除文档
* @param string $keyName 索引名
* @param string $id 文档id
* @return array|callable
*/
public function deleteDoc(string $keyName, string $id)
{
// 文档是否存在
$res = $this->existsDoc($keyName, $id);
if (!$res) {
throw new \think\Exception('文档不存在');
}
$params = [
'index' => $this->index_name .'_'. $keyName,
'type' => $this->type,
'id' => $id
];
return $this->client->delete($params);
}
/**
* 更新文档(字段内容)
* @param string $keyName 索引名
* @param string $id 文档id
* @param string $key 更新的字段
* @param string $value 更新的内容
* @return array|callable
*/
public function updateDoc(string $keyName, string $id, string $key, string $value)
{
// 文档是否存在
$res = $this->existsDoc($keyName, $id);
if (!$res) {
throw new \think\Exception('文档不存在');
}
// 可以灵活添加新字段,最好不要乱添加
$params = [
'index' => $this->index_name .'_'. $keyName,
'type' => $this->type,
'id' => $id,
'body' => [
'doc' => [
$key => $value
]
]
];
return $this->client->update($params);
}
/**
* 更新文档(数组)
* @param string $keyName 索引名
* @param string $id 文档id
* @param array $doc 更新的字段
* @return array|callable
*/
public function updateDocArray(string $keyName, string $id, array $doc)
{
// 文档是否存在
$res = $this->existsDoc($keyName, $id);
if (!$res) {
throw new \think\Exception('文档不存在');
}
// 可以灵活添加新字段,最好不要乱添加
$params = [
'index' => $this->index_name .'_'. $keyName,
'type' => $this->type,
'id' => $id,
'body' => ['doc'=>$doc]
];
return $this->client->update($params);
}
/**
* 获取文档
* @param string $keyName 索引名
* @param string $id 文档id
* @return array
*/
public function getDoc(string $keyName, string $id){
$params = [
'index' => $this->index_name .'_'. $keyName,
'type' => $this->type,
'id' => $id
];
$response = $this->client->get($params);
return $response['_source'];
}
/**
* es单字段模糊匹配
$sort 3维数组 例:'sort' => [
['time' => ['order' => 'desc']],
['popularity' => ['order' => 'desc']]
]
* @param string $keyName 索引名
* @param string $fieldName 字段名
* @param string $search 关键词
* @param int $from 起始位置
* @param int $size 文档数量
* @param array $sort 排序
* @return void
*/
function esSingleFieldSearch($keyName, $fieldName, $search, $from=0, $size=0, $sort=[])
{
$params = [
'index' => $this->index_name .'_'. $keyName,
'body' => [
'query' => [
'match' => [
$fieldName => $search
]
]
]
];
if($size != 0){
$params['body']['from'] = $from;
$params['body']['size'] = $size;
}
if(!empty($sort)){
$params['body']['sort'] = $sort;
}
$res = $this->client->search($params);
$res = array_column($res['hits']['hits'], '_source');
return $res;
}
/**
* es多字段模糊匹配同一数据
* param $fieldName 1维数组
param $includeFields 1维数组
param $sort 3维数组 例:
[
['time' => ['order' => 'desc']],
['popularity' => ['order' => 'desc']]
]
* @param string $keyName 索引名
* @param array $fieldName 字段名(多字段)
* @param string $search 关键词
* @param int $from 起始位置
* @param int $size 文档数量
* @param array $sort 排序
* @param array $includeFields 返回的字段
* @return void
*/
function esMultiFieldSearch($keyName, $fieldName=[], $search, $from=0, $size=0, $sort=[], $includeFields=[])
{
$params = [
'index' => $this->index_name .'_'. $keyName,
'body' => [
"query"=>[
"multi_match"=> [
"query" => $search,
"fields" => $fieldName
]
]
]
];
if($size!=0){
$params['body']['from'] = $from;
$params['body']['size'] = $size;
}
if(!empty($sort)){
$params['body']['sort'] = $sort;
}
if(!empty($includeFields)){
$params['body']["_source"] = $includeFields;
}
$res = $this->client->search($params);
$res = array_column($res['hits']['hits'], '_source');
return $res;
}
}