zincsearch服务类封装

<?php

namespace addons\zincsearchplug\service;

use Exception;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Psr\Http\Message\ResponseInterface;
use app\model\system\Config;
use think\Env;

class ZincsearchService
{

    protected $client;
    public function __construct()
    {
        $zincsearch_hosts = Config::build()->where('id', 1)->find();
        $this->client = new Client([
            'auth' => [$zincsearch_hosts['zincsearch_name'], $zincsearch_hosts['zincsearch_password']],
            'base_uri' => $zincsearch_hosts['zincsearch_hosts'],
            'timeout' => 3
        ]);
        $this->projectName = 'liangzhu_'; // 索引名(项目名)
    }

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

    /**
     * 处理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 [type] $keyName    索引名
     * @param [type] $fieldName  字段
     * @param [type] $keywords   匹配词
     * @param [type] $form       起始位置
     * @param [type] $size       条数
     * @return void
     */
    function esIndexSearchAllDel($index, $fieldName, $keywords, $form = 0, $size = 10000)
    {
        $params = [
            'query' => [
                'bool' => [
                    'must' => [
                        'term' => [
                            $fieldName => $keywords
                        ],
                    ],
                ],
            ],
        ];
        $params['form'] = $form;
        $params['size'] = $size;

        $indexName = $this->projectName . $index;
        $resp = $this->client->request('POST', "/es/$indexName/_delete_by_query", ['json' => $params]);
        $result = $this->handleJson($resp);
        return $result;
    }

    /**
     * 获取统计数量
     * @param [type] $keyName    索引名
     * @param [type] $fieldName  字段
     * @param [type] $keywords   匹配词
     * @return void
     */
    function esIndexSearchAllDataTotal($index, $fieldName, $keywords)
    {
        $params = [
            'query' => [
                'bool' => [
                    'must' => [
                        'term' => [
                            $fieldName => $keywords
                        ],
                    ],
                ],
            ],
        ];

        $indexName = $this->projectName . $index;
        $resp = $this->client->request('POST', "/es/$indexName/_search", ['json' => $params]);
        $result = $this->handleJson($resp);
        return $result['hits']['total']['value'];
    }



    /**
     * 文章相似推荐(同模型或同栏目)
     * @param $index string 索引
     * @param $field string 搜索的字段名
     * @param $keyword string 关键词
     * @param $id string 主键的值(相似推荐排除自己)
     * @param $form int 开始查询的下标,默认为0
     * @param $size int 查询的条数,默认为20
     * @param $searchTypeKey string 同模型或同栏目
     * @param $searchTypeValue int 栏目或模型id
     * @param $order string 排序
     * @return array
     * @throws GuzzleException
     * @throws Exception
     */
    public function esSameRecommend($index, $field, $keyword, $id, $form = 0, $size = 20, $searchTypeKey, $searchTypeValue, $order)
    {
        $indexName = $this->projectName . $index;
        $searchTypeValueMin = $searchTypeValue - 1;
        $searchTypeValueMax = $searchTypeValue + 1;
        $json = [
            'query' => [
                'bool' => [
                    'must' => [
                        'match' => [
                            $field => [
                                'query' => $keyword,
                            ]
                        ]
                    ],
                    // 排除id
                    'must_not' => [
                        'match' => [
                            'id' => [
                                'query' => $id
                            ]
                        ]
                    ],
                    // 复杂的搜索,筛选出mid等于x的
                    'filter' => [
                        'range' => [
                            $searchTypeKey => [
                                'gt' => $searchTypeValueMin,
                                'lt' => $searchTypeValueMax
                            ]
                        ]
                    ],
                ]
            ],
        ];
        if ($size != 0) {
            $json['from'] = $form;
            $json['size'] = $size;
        }
        if (!empty($order)) {
            $json['sort'] = [
                ['create_time' => ['order' => $order]]
            ];
        }

        $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 $field string 搜索的字段名
     * @param $keyword string 关键词
     * @param $id string 主键的值(相似推荐排除自己)
     * @param $form int 开始查询的下标,默认为0
     * @param $size int 查询的条数,默认为20
     * @param $order string 排序
     * @return array
     * @throws GuzzleException
     * @throws Exception
     */
    public function esRecommend($index, $field, $keyword, $id, $form = 0, $size = 20, $order)
    {
        $indexName = $this->projectName . $index;
        $json = [
            'query' => [
                'bool' => [
                    'must' => [
                        'match' => [
                            $field => [
                                'query' => $keyword,
                            ]
                        ]
                    ],
                    // 排除id
                    'must_not' => [
                        'match' => [
                            'id' => [
                                'query' => $id
                            ]
                        ]
                    ],
                ]
            ],
        ];
        if ($size != 0) {
            $json['from'] = $form;
            $json['size'] = $size;
        }
        if (!empty($order)) {
            $json['sort'] = [
                ['create_time' => ['order' => $order]]
            ];
        }

        $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, $sourceType = 1)
    {
        $indexName = $this->projectName . $index;
        $resp = $this->client->request('POST', "/es/$indexName/_search", ['json' => $params]);
        $result =  $this->handleJson($resp);
        if ($sourceType == 1) {
            $result = $result['hits']['hits'];
            return array_column($result, '_source');
        } else {
            return $result;
        }
    }



    /**
     * 搜索
     * @param $index string 索引
     * @param $field string 搜索的字段名
     * @param $keyword string 关键词
     * @param $form int 开始查询的下标,默认为0
     * @param $size int 查询的条数,默认为20
     * @param $order string 排序
     * @return array
     * @throws GuzzleException
     * @throws Exception
     */
    public function esSearch($index, $field, $keyword, $form = 0, $size = 20, $order)
    {
        $indexName = $this->projectName . $index;
        $json = [
            'query' => [
                'bool' => [
                    'must' => [
                        'match' => [
                            $field => [
                                'query' => $keyword,
                            ]
                        ]
                    ],
                ]
            ],
        ];
        if ($size != 0) {
            $json['from'] = $form;
            $json['size'] = $size;
        }
        if (!empty($order)) {
            $json['sort'] = [
                ['create_time' => ['order' => $order]]
            ];
        }

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


    /**
     * 获取统计数量
     * @param [type] $keyName    索引名
     * @param [type] $fieldName  字段
     * @param [type] $keywords   匹配词
     * @return void
     */
    function esSearchDataTotal($index, $fieldName, $keywords)
    {
        $params = [
            'query' => [
                'bool' => [
                    'must' => [
                        'match' => [
                            $fieldName => $keywords
                        ],
                    ],
                ],
            ],
        ];

        $indexName = $this->projectName . $index;
        $resp = $this->client->request('POST', "/es/$indexName/_search", ['json' => $params]);
        $result = $this->handleJson($resp);
        return $result['hits']['total']['value'];
    }


    /**
     * 判断指定的索引名是否存在
     * @param indexName 索引名
     * @return  存在:1; 不存在:0;
     */
    function isExistsIndex($index)
    {
        $indexName = $this->projectName . $index;
        try {
            $resp = $this->client->request('GET', "/api/index/$indexName");
            $result = 1;
        } catch (\Throwable $th) {
            $result = 0;
        }
        return $result;
    }

    /**
     * 创建索引
     * @param [type] $keyName    索引名
     * @return void
     */
    function addZincsearchIndex($index)
    {
        // 如果索引已存在,则直接返回true
        if ($this->isExistsIndex($index)) {
            return true;
        }
        $indexName = $this->projectName . $index;
        $params = [
            'name' => $indexName,
            'storage_type' => 'disk',
            'shard_num' => 3, // 服务器分片数,默认为3
            'mappings' => [
                'properties' => [
                    'title' => [
                        'type' => 'text',
                        'index' => true,
                        'store' => true,
                        'highlightable' => false,
                        'sortable' => false,
                        'aggregatable' => false,
                        'analyzer' => 'gse_standard',
                    ],
                    'mid' => [
                        "type" => "numeric",
                        "index" => true,
                        "store" => false,
                        "sortable" => true,
                        "aggregatable" => true,
                        "highlightable" => false
                    ],
                    'cid' => [
                        "type" => "numeric",
                        "index" => true,
                        "store" => false,
                        "sortable" => true,
                        "aggregatable" => true,
                        "highlightable" => false
                    ],
                    'id' => [
                        "type" => "numeric",
                        "index" => true,
                        "store" => false,
                        "sortable" => true,
                        "aggregatable" => true,
                        "highlightable" => false
                    ],

                    'create_time' => [
                        'type' => 'keyword',
                        'index' => false,
                        'store' => true,
                        'highlightable' => false,
                        'sortable' => false,
                        'aggregatable' => false,
                    ],
                    'desc' => [
                        'type' => 'keyword',
                        'index' => false,
                        'store' => true,
                        'highlightable' => false,
                        'sortable' => false,
                        'aggregatable' => false,
                    ],
                    'cover' => [
                        'type' => 'keyword',
                        'index' => false,
                        'store' => true,
                        'highlightable' => false,
                        'sortable' => false,
                        'aggregatable' => false,
                    ],
                    'click' => [
                        'type' => 'keyword',
                        'index' => false,
                        'store' => true,
                        'highlightable' => false,
                        'sortable' => false,
                        'aggregatable' => false,
                    ],
                    'uuid' => [
                        'type' => 'keyword',
                        'index' => false,
                        'store' => true,
                        'highlightable' => false,
                        'sortable' => false,
                        'aggregatable' => false,
                    ],
                    'user_id' => [
                        'type' => 'keyword',
                        'index' => false,
                        'store' => true,
                        'highlightable' => false,
                        'sortable' => false,
                        'aggregatable' => false,
                    ],
                ]
            ]
        ];

        $resp = $this->client->request('POST', "/api/index", ['json' => $params]);
        return $this->handleJson($resp);
    }


}

 

posted @ 2023-05-07 16:57  潘潘潘的博客  阅读(200)  评论(0编辑  收藏  举报