zincsearch服务类封装

潘潘潘的博客 / 2023-05-07 / 原文

<?php

namespace ZincSearch;

use Exception;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Psr\Http\Message\ResponseInterface;

class ZincSearchService
{

    protected $client;

    public static function build()
    {
        return new self();
    }

    public function __construct()
    {
        $this->client = new Client([
            'auth' => [
                'admin',
                '123456',
            ],
            'base_uri' => 'http://127.0.0.1:4080',
            'timeout' => 3
        ]);
        $this->projectName = 'jiuyu_'; // 索引名(项目名)
    }

    /**
     * 处理json数据
     * @param ResponseInterface $resp
     * @return mixed
     * @throws Exception
     */
    public function handleJson(ResponseInterface $resp)
    {
        if ($resp->getStatusCode() !== 200) {
            throw new Exception('请求失败,失败原因:' . $resp->getBody(), $resp->getStatusCode());
        }
        $body = $resp->getBody();
        return json_decode($body, true);
    }

    /**
     * 获取zincSearch版本
     * @return mixed
     * @throws GuzzleException
     * @throws Exception
     */
    public function version()
    {
        $resp = $this->client->get('/version');
        return $this->handleJson($resp);
    }

    /**
     * 批量新增或者批量更新
     * @param $index string 索引
     * @param $primaryKey string 主键
     * @param $data array 数据
     * @return mixed
     * @throws GuzzleException
     * @throws Exception
     */
    public function bulk($index, $primaryKey, array $data)
    {
        $params = [];
        $key = 0;
        $indexName = $this->projectName . $index;
        foreach ($data as $v) {
            $params[$key]['index'] = [
                '_index' => $indexName,
                '_id' => strval($v[$primaryKey]),
            ];
            $key++;
            $params[$key] = $v;
            $key++;
        }
        // 把数组转化成ndjson
        $ndjson = "";
        foreach ($params as $key => $item) {
            $json = json_encode($item);
            if (isset($params[$key + 1])) {
                $ndjson .= $json . PHP_EOL;
            } else {
                $ndjson .= $json;
            }
        }
        $resp = $this->client->request('POST', "/api/_bulk", ['body' => $ndjson]);
        return $this->handleJson($resp);
    }

    /**
     * 批量新增(不能指定zincSearch的主键)
     * @param $index string 索引
     * @param $data array 数据
     * @return mixed
     * @throws GuzzleException
     * @throws Exception
     */
    public function bulkV2($index, $data)
    {
        $indexName = $this->projectName . $index;
        $params = [
            'index' => $indexName,
        ];
        foreach ($data as $k => $v) {
            $params['records'][$k] = $v;
        }
        $resp = $this->client->request('POST', "/api/_bulkv2", ['json' => $params]);
        return $this->handleJson($resp);
    }

    /**
     * 新增或者编辑
     * @param $index string 索引
     * @param $id string 主键的值
     * @param $data array 数据
     * @return mixed
     * @throws GuzzleException
     * @throws Exception
     */
    public function createOrUpdate($index, $id, $data)
    {
        $indexName = $this->projectName . $index;
        $resp = $this->client->request('PUT', "/api/$indexName/_doc/$id", ['json' => $data]);
        return $this->handleJson($resp);
    }

    /**
     * 删除
     * @param $index string 索引
     * @param $id string 主键的值
     * @return mixed
     * @throws GuzzleException
     * @throws Exception
     */
    public function delete($index, $id)
    {
        $indexName = $this->projectName . $index;
        $resp = $this->client->request('DELETE', "/api/$indexName/_doc/$id");
        return $this->handleJson($resp);
    }

    /**
     * 搜索
     * @param $index string 索引
     * @param $keyword string 关键词
     * @param $filed array 需要显示的字段
     * @param $from int 开始查询的下标,默认为0
     * @param $maxResult int 查询的条数,默认为20
     * @param $searchType string 搜索模式,默认为match
     * @return array
     * @throws GuzzleException
     * @throws Exception
     */
    public function search($index, $keyword, array $filed = [], $from = 0, $maxResult = 20, $searchType = 'match')
    {
        $indexName = $this->projectName . $index;
        $json = [
            'search_type' => $searchType,
            'query' => [
                'term' => $keyword
            ],
            'from' => $from,
            'max_results' => $maxResult,
            '_source' => $filed
        ];

        $resp = $this->client->request('POST', "/api/$indexName/_search", ['json' => $json]);
        $result =  $this->handleJson($resp);
        $result = $result['hits']['hits'];
        return array_column($result, '_source');
    }

    /**
     * 相似推荐
     * @param $index string 索引
     * @param $field string 搜索的字段名
     * @param $keyword string 关键词
     * @param $idField string 主键
     * @param $id string 主键的值(相似推荐排除自己)
     * @param $form int 开始查询的下标,默认为0
     * @param $size int 查询的条数,默认为20
     * @return array
     * @throws GuzzleException
     * @throws Exception
     */
    public function esSearch($index, $field, $keyword, $idField, $id, $form = 0, $size = 20)
    {
        $indexName = $this->projectName . $index;
        $json = [
            'query' => [
                'bool' => [
                    'must' => [
                        'match' => [
                            $field => [
                                'query' => $keyword,
                            ]
                        ]
                    ],
                    'must_not' => [
                        'match' => [
                            $idField => [
                                'query' => $id
                            ]
                        ]
                    ]
                ]
            ],
            'from' => $form,
            'size' => $size,
        ];
        $resp = $this->client->request('POST', "/es/$indexName/_search", ['json' => $json]);
        $result =  $this->handleJson($resp);
        $result = $result['hits']['hits'];
        return array_column($result, '_source');
    }


    /**
     * 按条件获取数据列表
     * @param $index string 索引
     * @param $params array 搜索的条件
     * @return array
     * @throws GuzzleException
     * @throws Exception
     */
    public function request($index, $params)
    {
        $indexName = $this->projectName . $index;
        $resp = $this->client->request('POST', "/es/$indexName/_search", ['json' => $params]);
        $result =  $this->handleJson($resp);
        $result = $result['hits']['hits'];
        return array_column($result, '_source');
    }
}