1. 程式人生 > 實用技巧 >ELASTIC-PHP + IK分詞器 + THINKPHP6 初次使用 (關鍵詞查詢)

ELASTIC-PHP + IK分詞器 + THINKPHP6 初次使用 (關鍵詞查詢)

環境:centos 6 php73 mysql56 ELASTIC7.71

1.安裝elastic 使用華為雲映象更快哦https://mirrors.huaweicloud.com/elasticsearch/

wget https://mirrors.huaweicloud.com/elasticsearch/7.7.1/elasticsearch-7.7.1-linux-x86_64.tar.gz

tar -zxvf elasticsearch-7.7.1-linux-x86_64.tar.gz 

2.新增使用者(使用者啟動elastic 不能用root所以) 去目錄裡面編輯配置 elastic.yml

groupadd elastic
useradd -g elastic elastic
chown -R elastic.elastic /etc/elasticsearch-7.7.1
vim config/elasticsearch.yml 

  配置如下 注意冒號後有空格

------------------------------------ Node ------------------------------------
#
# Use a descriptive name for the node:
#
node.name: hxx-node-1
#
# Add custom attributes to the node:
#
#node.attr.rack: r1
#
# ----------------------------------- Paths ------------------------------------
#
# Path to directory where to store the data (separate multiple locations by comma):
#
path.data: /var/elastic/data
#
# Path to log files:
#
path.logs: /var/elastic/logs
#
# ----------------------------------- Memory -----------------------------------
#
# Lock the memory on startup:
#
#bootstrap.memory_lock: true
#
# Make sure that the heap size is set to about half the memory available
# on the system and that the owner of the process is allowed to use this
# limit.
#
# Elasticsearch performs poorly when the system is swapping the memory.
#
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
#
network.host: 127.0.0.1
#
# Set a custom port for HTTP:
#
http.port: 9200
#
# For more information, consult the network module documentation.
# on the system and that the owner of the process is allowed to use this
# limit.
#
# Elasticsearch performs poorly when the system is swapping the memory.
#
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
#
network.host: 127.0.0.1
#
# Set a custom port for HTTP:
#
http.port: 9200
#
# For more information, consult the network module documentation.
#
# --------------------------------- Discovery ----------------------------------
#
# Pass an initial list of hosts to perform discovery when this node is started:
# The default list of hosts is ["127.0.0.1", "[::1]"]
#
#discovery.seed_hosts: ["host1", "host2"]
#
# Bootstrap the cluster using an initial set of master-eligible nodes:
#
cluster.initial_master_nodes: ["hxx-node-1"]

cluster.routing.allocation.disk.watermark.flood_stage: 99%
cluster.routing.allocation.disk.threshold_enabled: false

  3.安裝ik分詞庫(用於中文) 下載對應的哦 7.7.1

https://github.com/medcl/elasticsearch-analysis-ik/releases

不管你用何種方法 放到安裝路徑裡/etc/elasticsearch-7.7.1/plugins/ik

好了 切換到 elastic 然後執行elastic

su elastic
./bin/elastic -d

 可進行測試

[root@iZuf64idor3ej85kby45arZ elasticsearch-7.7.1]# curl 127.0.0.1:9200
{
  "name" : "hxx-node-1",
  "cluster_name" : "hxx",
  "cluster_uuid" : "-43vGhX0Ru2ocVqNO7VhyA",
  "version" : {
    "number" : "7.7.1",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "ad56dce891c901a492bb1ee393f12dfff473a423",
    "build_date" : "2020-05-28T16:30:01.040088Z",
    "build_snapshot" : false,
    "lucene_version" : "8.5.1",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"

  二、PHP部分

1.composer 引入 elastic-php(使用phpstorm更方便)

"elasticsearch/elasticsearch": "~7.0",

  2.編輯elastic控制器類(包括 建立 增刪改查 批量給匯入)Ela.php

(1)執行index 後面查詢執行search

<?php

// +----------------------------------------------------------------------
// | EasyAdmin
// +----------------------------------------------------------------------
// | PHP交流群: 763822524
// +----------------------------------------------------------------------
// | 開源協議  https://mit-license.org 
// +----------------------------------------------------------------------
// | github開源專案:https://github.com/zhongshaofa/EasyAdmin
// +----------------------------------------------------------------------

namespace app\index\controller;

use app\admin\model\Corporation;
use app\index\model\SystemUploadfile;
use app\common\controller\IndexController;
use app\common\service\MenuService;
use EasyAdmin\upload\Uploadfile;
use Elasticsearch\ClientBuilder;
use Elasticsearch\Common\Exceptions\BadRequest400Exception;
use Elasticsearch\Common\Exceptions\ElasticsearchException;
use Elasticsearch\Common\Exceptions\Missing404Exception;
use think\db\Query;
use think\facade\Cache;

class Ela extends IndexController
{

    private $client;

    // 建構函式
    public function __construct()
    {
        //$host = ['120.26.205.129:9200'];
        $host = ['127.0.0.1:9200'];
        $this->index = 'hcc_corporation';
        //$this->type = 'lyric';
        $this->client = ClientBuilder::create()->setHosts($host)->build();
    }

    // 初始化
    public function index()
    {


        // 只能建立一次


        $this->delete_index();

        $this->create_index(); //1.建立索引

        $this->create_mappings(); //2.建立文件模板



        /* foreach ($docs as $k => $v) {
             $this->add_doc($v['id'], $v); //3.新增文件
             echo '<pre>';
             print_r($this->get_doc($v['id']));
         }
         exit();*/
//        echo '<pre>';
//        print_r($this->get_doc(512));
//        exit();

//        $re = $this->search_doc("我做無敵",0,2); //4.搜尋結果
//
//        echo '<pre>';
//        print_r($re);
//        exit();
        echo '<pre>';
        print_r("INIT OK");
        exit();
    }


    public function put_settings()
    {
        $params1 =
            [

                'index' => $this->index,
                'body' => [
                    'settings' => [
                        'blocks' =>
                            [
                                'read_only_allow_delete' => 'false'
                            ]
                    ],
                ]
            ];
        $this->client->indices()->putSettings($params1);
        echo 'SUCCESS';
    }

    // 建立索引

    public function create_index()
    { // 只能建立一次
        $params = [
            'index' => $this->index,
            'body' => [
                'settings' => [
                    'number_of_shards' => 3,
                    'number_of_replicas' => 2,
                    'blocks' =>
                        [
                            'read_only_allow_delete' => 'false'
                        ],
                    /*'transient' =>
                        [
                            'cluster' =>
                                [
                                    'routing' =>
                                        [
                                            'allocation' =>
                                                [
                                                    'disk' =>
                                                        [
                                                            'threshold_enabled' => 'true',
                                                            'watermark' =>
                                                                [
                                                                    'flood_stage' => '99%'
                                                                ]
                                                        ]
                                                ]
                                        ]
                                ]
                        ]*/
                ],
            ]
        ];


        try {


            $this->client->indices()->create($params);


        } catch (BadRequest400Exception $e) {
            $msg = $e->getMessage();
            $msg = json_decode($msg, true);
            return $msg;
        }
    }


    // 刪除索引
    public function delete_index()
    {

        $params = ['index' => $this->index];
        $index = $this->client->indices()->get($params);

        if ($index) {
            return $this->client->indices()->delete($params);
        }

        //

    }

    // 建立文件模板
    public function create_mappings()
    {

        /*--------------------允許type的寫法 老版本 已去除--------------------------*/


        /*--------------------不允許type的寫法--------------------------*/
        // Set the index and type
        $params = [
            'index' => $this->index,
            'body' => [
                '_source' => [
                    'enabled' => true
                ],
                'properties' => [
                    'id' => [
                        'type' => 'integer',
                    ],
                    'name' => [
                        'type' => 'text',
                        'analyzer' => 'ik_smart'
                        // 'analyzer' => 'keyword'
                    ],

                    /*-------------------------------------*/

                    /*'profile' => [
                        'type' => 'text',
                        'analyzer' => 'ik_max_word'
                    ],
                    'age' => [
                        'type' => 'integer',
                    ],*/
                ]
            ]
        ];

        $this->client->indices()->putMapping($params);

        /*       echo '<pre>';
               print_r('success');
               exit();*/
    }

    // 檢視對映
    public function get_mapping()
    {
        $params = [
            'index' => $this->index,
        ];
        $re = $this->client->indices()->getMapping($params);
        echo '<pre>';
        print_r($re);
        exit();

    }

    // 新增一個文件(記錄)
    public function add_doc($id, $doc)
    {
        $params = [

            'index' => $this->index,
            //  'type' => $this->type,
            'id' => $id,
            'body' => $doc
        ];

        return $this->client->index($params);

    }

    // 判斷文件(記錄)
    public function exists_doc($id = 1)
    {
        $params = [
            'index' => $this->index,
            'type' => $this->type,
            'id' => $id
        ];

        return $this->client->exists($params);

    }

    // 獲取一條文件(記錄)
    public function get_doc($id = 1)
    {
        $params =
            [
                'index' => $this->index,
                // 'type' => $this->type,
                'id' => $id
            ];

        try {

            $re = $this->client->get($params);

        } catch (Missing404Exception $e) {

            echo '<pre>';
            print_r('未找到對應資料');
            exit();

        }

        echo '<pre>';
        print_r($re);
        exit();

    }

    // 更新一條文件()
    public function update_doc($id = 1)
    {
        // 可以靈活新增新欄位,最好不要亂新增
        $params = [
            'index' => $this->index,
            'id' => $id,
            'body' => [
                'doc' => [
                    'name' => '大王'
                ]
            ]
        ];

        return $this->client->update($params);

    }

    // 刪除一條文件()
    public function delete_doc($id = 1)
    {
        $params = [
            'index' => $this->index,
            //'type' => $this->type,
            'id' => $id
        ];

        return $this->client->delete($params);

    }

    // 查詢文件 (分頁,排序,權重,過濾)
    public function search_doc($keywords = "", $from = 0, $size = 10, $order = ['id' => ['order' => 'desc']])
    {

        /*   echo '<pre>';
           print_r($from);
           print_r($size);
           exit();*/
        $keywords_arr = array_filter(explode(" ", $keywords));
        $query = '';
        $number = count($keywords_arr);
        if($number > 10){
            return "ERROR";
        }
        if ($number > 1) {
            $arr = [];
            foreach ($keywords_arr as $ka){
                $arr[] = $ka;
            }
            $mathc_phrase = [];

            switch ($number){
                case 2:
                    $mathc_phrase =
                        [
                            'name'=>$arr[0],
                            'name'=>$arr[1]
                        ];
                    break;
                case 3:
                    $mathc_phrase =
                        [
                            'name'=>$arr[0],
                            'name'=>$arr[1],
                            'name'=>$arr[2]
                        ];
                    break;
                case 4:
                    $mathc_phrase =
                        [
                            'name'=>$arr[0],
                            'name'=>$arr[1],
                            'name'=>$arr[2],
                            'name'=>$arr[3],
                        ];
                    break;
                case 5:
                    $mathc_phrase =
                        [
                            'name'=>$arr[0],
                            'name'=>$arr[1],
                            'name'=>$arr[2],
                            'name'=>$arr[3],
                            'name'=>$arr[4],
                        ];
                    break;
                case 6:
                    $mathc_phrase =
                        [
                            'name'=>$arr[0],
                            'name'=>$arr[1],
                            'name'=>$arr[2],
                            'name'=>$arr[3],
                            'name'=>$arr[4],
                            'name'=>$arr[5],
                        ];
                    break;
                case 7:
                    $mathc_phrase =
                        [
                            'name'=>$arr[0],
                            'name'=>$arr[1],
                            'name'=>$arr[2],
                            'name'=>$arr[3],
                            'name'=>$arr[4],
                            'name'=>$arr[5],
                            'name'=>$arr[6],
                        ];
                    break;
                case 8:
                    $mathc_phrase =
                        [
                            'name'=>$arr[0],
                            'name'=>$arr[1],
                            'name'=>$arr[2],
                            'name'=>$arr[3],
                            'name'=>$arr[4],
                            'name'=>$arr[5],
                            'name'=>$arr[6],
                            'name'=>$arr[7],
                        ];
                    break;
                case 9:
                    $mathc_phrase =
                        [
                            'name'=>$arr[0],
                            'name'=>$arr[1],
                            'name'=>$arr[2],
                            'name'=>$arr[3],
                            'name'=>$arr[4],
                            'name'=>$arr[5],
                            'name'=>$arr[6],
                            'name'=>$arr[7],
                            'name'=>$arr[8],
                        ];
                    break;
                case 10:
                    $mathc_phrase =
                        [
                            'name'=>$arr[0],
                            'name'=>$arr[1],
                            'name'=>$arr[2],
                            'name'=>$arr[3],
                            'name'=>$arr[4],
                            'name'=>$arr[5],
                            'name'=>$arr[6],
                            'name'=>$arr[7],
                            'name'=>$arr[8],
                            'name'=>$arr[9],
                        ];
                    break;

            }

           // $should = [];
            /*foreach ($keywords_arr as $k => $keyword) {

                 //   $query .= $keyword . " OR ";
                $mathc_phrase[] = ['name'=>$keyword];

            }*/
          //  $query = substr($query,0,strlen($query)-3);

            $query_func = [
                'bool' =>
                    [
                        'must' =>
                            [
                                //$should

                                //$mathc_phrase
                                /*'query_string' =>
                                    [
                                        'default_field' => 'name',
                                        'query' => $query
                                    ]*/


                                'match_phrase'=>$mathc_phrase,
                               /*  'match_phrase'=>
                                [
                                    'name'=>'研究會',
                                ]*/
                            ]
                    ]


            ];
            /*echo '<pre>';
            print_r($query_func);
            exit();*/
        } else {
           // $query = $keywords;

            $query_func = [

                /*-----------------------------name 單欄位單匹配---------------------------*/
                'bool' =>
                    [
                        'should' =>
                            [
                                'match_phrase' =>
                                    [
                                        'name' => $keywords
                                    ]
                            ]
                    ]

            ];
        }

        if ($keywords) {
            $params = [
                'index' => $this->index,
                //  'type' => $this->type,
                'body' => [
                    'query' => $query_func,

                    'sort' =>
                        [$order],
                    'from' => $from,
                    'size' => $size
                ]
            ];

        } else {
            $params = [
                'index' => $this->index,
                //  'type' => $this->type,
                'body' => [
                    /* 'query' => [
                         'match_all'=>[]
                     ],*/
                    'sort' => [$order]
                    , 'from' => $from, 'size' => $size
                ]
            ];
        }


        try {
            $re = $this->client->search($params);
        } catch (\Exception $e) {
            echo '<pre>';
            print_r($e->getMessage());
            exit();
        }


        return $re;
    }


    /**
     * 批量插入資料到索引
     */
    public function insertCorporation()
    {
        $corporations = Corporation::select();
        foreach ($corporations as $corporation) {

            $corporation = $corporation->toArray();

            $this->add_doc($corporation['id'], $corporation);
        }
        echo '<pre>';
        print_r('完成了');
        exit();
    }

}

  實際案例:http://www.huixx.cn/search/corporation.html?keyword=