elastic-php实现多个OR并列查询的优化

具体要求是一个关键词查询,可以查询名称或者标签或者所属的行业(通过名称模糊匹配ID)

主要是在must中嵌入 [bool][should]  进行OR的连接
 

然后query_string使用多字段 进行查询 name 和labels.核心代码如下

  if ($keywords) {
            /*获取单词的分词情况*/
            $analyzer = $this->client->indices()->analyze(
                [
                    'index' => $this->index,
                    'body' =>
                        [
                            'text' => $keywords,
                            'analyzer' => 'ik_max_word'
                        ]
                ]
            );
            if ($analyzer) {
                $tokens = $analyzer['tokens'];
                $keys = array_column($tokens, 'token', NULL);

                $keys_OR = implode('AND', $keys);
                //分词和labels同时查询
                $must_arr['bool']['should'][0]['query_string'] = ['fields' => ['name','labels'], 'query' => $keys_OR];
            }else{
//没有分词就直接查询labels
                $must_arr['bool']['should'][0]['query_string'] = ['default_field' => 'labels', 'query' => $keywords];
            }



        }


        if ($pro) {
//加入获取到的profession
            $must_arr['bool']['should'][1]['term']['profession'] = $pro;
        }


完整方法

 // 查询文档 (分页,排序,权重,过滤)
    public function search_doc($keywords = "", $year_arr = '', $province_arr = [], $from = 0, $size = 10, $order = ['id' => ['order' => 'asc']], $pro = 0)
    {

        $must_arr = [];
        $filter_arr = [];
        $should_arr = [];
        $keys = '';

        if ($keywords) {
            /*获取单词的分词情况*/
            $analyzer = $this->client->indices()->analyze(
                [
                    'index' => $this->index,
                    'body' =>
                        [
                            'text' => $keywords,
                            'analyzer' => 'ik_max_word'
                        ]
                ]
            );
              if ($analyzer) {
                $tokens = $analyzer['tokens'];
                $keys = array_column($tokens, 'token', NULL);

                $keys_OR = implode('AND', $keys);
                //分词和labels同时查询
                $must_arr['bool']['should'][0]['query_string'] = ['fields' => ['name','labels'], 'query' => $keys_OR];
            }else{
//没有分词就直接查询labels
                $must_arr['bool']['should'][0]['query_string'] = ['default_field' => 'labels', 'query' => $keywords];
            }



        }


        if ($pro) {
//加入获取到的profession
            $must_arr['bool']['should'][1]['term']['profession'] = $pro;
        }


        //查询审核通过的数据
        $filter_arr[]['term']['checked'] = 1;

        //按照给定年份 或者年份范围查询
        if ($year_arr && $year_arr[0] > 0) {
            $filter_arr[]['range'] = ['create_date' => ['gte' => $year_arr[0] . "-01-01", 'lte' => $year_arr[1] . "-12-31"]];
        }

        if ($province_arr) {
            if (!is_array($province_arr) && $province_arr !== 0) {
                $province_arr = explode(',', $province_arr);
            }

            //按照给定省份查询

            if ($province_arr !== 0 && ($province_arr[0] ?? 0) !== 0 && count($province_arr) > 0) {
                $filter_arr[]['terms']['province.keyword'] = $province_arr;
            }
        }


        /* echo "<pre>";
         print_r($filter_arr);
         print_r($province_arr);
         exit();*/

        if ($keywords || $year_arr || ($province_arr != 0 && count($province_arr) > 0)) {

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

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


            $params = [
                'index' => $this->index,
                //  'type' => $this->type,
                'body' => [
                    'query' => [
//                          'match' =>
//                          [
//                              'name'=>$keywords
//                          ]
                        'bool' =>
                            [
                                //  'filter'=>[
                                'must' => $must_arr,
                                'filter' => $filter_arr,
                                'should' => $should_arr,
                                //  ],
                            ]
                    ],

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

            /*echo "<pre>";
            print_r(json_encode($params['body']['query']));
            exit();*/

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


        } // ------------------------------------------------------------------------


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

        try {

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

        } catch (\Exception $e) {
            echo '<pre>';
            print_r($e->getMessage());
            exit();
        }
        return ['re' => $re, 'keys' => $keys];
    }

完整文件:

<?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\Missing404Exception;
use think\db\Query;
use think\facade\Cache;
use think\facade\Queue;

class Ela extends IndexController
{

    private $client;

    // 构造函数
    public function __construct()
    {
        $host = ['127.0.0.1:9200'];
        $this->index = 'hcc_corporation_v2';
        //  $this->index = 'hcc_corporation';
        $this->client = ClientBuilder::create()->setHosts($host)->build();
    }

    // 初始化
    public function index()
    {
        // 只能创建一次
        echo '<pre>';
        print_r("OVER");
        exit();

        $this->delete_index();


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

        $this->create_mappings(); //2.创建文档模板

        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'
                        ],
                ],
            ]
        ];


        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',
                    ],
                    'top' => [
                        'type' => 'integer',
                    ],
                    'is_govern' => [
                        'type' => 'integer',
                    ],

                    'name' => [
                        'type' => 'text',
                        //'analyzer' => 'ik_max_word'
                        'analyzer' => 'ik_max_word'
                    ],
                    /*-------------------------------------*/
                ]
            ]
        ];

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

    // 查看映射
    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)
    {
        $get = $this->get_doc($id);

        if (!$get) {
            $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,
                'id' => $id
            ];

        try {

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

        } catch (Missing404Exception $e) {
            return 0;
            //return false;
        }

        return 1;
    }

    // 更新一条文档()
    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 = "", $year_arr = '', $province_arr = [], $from = 0, $size = 10, $order = ['id' => ['order' => 'asc']], $pro = 0)
    {

        $must_arr = [];
        $filter_arr = [];
        $should_arr = [];
        $keys = '';

        if ($keywords) {
            /*获取单词的分词情况*/
            $analyzer = $this->client->indices()->analyze(
                [
                    'index' => $this->index,
                    'body' =>
                        [
                            'text' => $keywords,
                            'analyzer' => 'ik_max_word'
                        ]
                ]
            );
             if ($analyzer) {
                $tokens = $analyzer['tokens'];
                $keys = array_column($tokens, 'token', NULL);

                $keys_OR = implode('AND', $keys);
                //分词和labels同时查询
                $must_arr['bool']['should'][0]['query_string'] = ['fields' => ['name','labels'], 'query' => $keys_OR];
            }else{
//没有分词就直接查询labels
                $must_arr['bool']['should'][0]['query_string'] = ['default_field' => 'labels', 'query' => $keywords];
            }



        }


        if ($pro) {
//加入获取到的profession
            $must_arr['bool']['should'][1]['term']['profession'] = $pro;
        }

        //查询审核通过的数据
        $filter_arr[]['term']['checked'] = 1;

        //按照给定年份 或者年份范围查询
        if ($year_arr && $year_arr[0] > 0) {
            $filter_arr[]['range'] = ['create_date' => ['gte' => $year_arr[0] . "-01-01", 'lte' => $year_arr[1] . "-12-31"]];
        }

        if ($province_arr) {
            if (!is_array($province_arr) && $province_arr !== 0) {
                $province_arr = explode(',', $province_arr);
            }

            //按照给定省份查询

            if ($province_arr !== 0 && ($province_arr[0] ?? 0) !== 0 && count($province_arr) > 0) {
                $filter_arr[]['terms']['province.keyword'] = $province_arr;
            }
        }


        /* echo "<pre>";
         print_r($filter_arr);
         print_r($province_arr);
         exit();*/

        if ($keywords || $year_arr || ($province_arr != 0 && count($province_arr) > 0)) {

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

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


            $params = [
                'index' => $this->index,
                //  'type' => $this->type,
                'body' => [
                    'query' => [
//                          'match' =>
//                          [
//                              'name'=>$keywords
//                          ]
                        'bool' =>
                            [
                                //  'filter'=>[
                                'must' => $must_arr,
                                'filter' => $filter_arr,
                                'should' => $should_arr,
                                //  ],
                            ]
                    ],

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

            /*echo "<pre>";
            print_r(json_encode($params['body']['query']));
            exit();*/

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


        } // ------------------------------------------------------------------------


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

        try {

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

        } catch (\Exception $e) {
            echo '<pre>';
            print_r($e->getMessage());
            exit();
        }
        return ['re' => $re, 'keys' => $keys];
    }


    /**
     * 批量插入数据到索引
     */
    public function insertCorporation($start)
    {
        echo '<pre>';
        print_r("OVER");
        exit();
        $corporations = Corporation::limit($start, 50000)->order('id ASC')->select();
        foreach ($corporations as $corporation) {
            $job = "index/Message2";
            Queue::push($job, $corporation->toArray(), $queue = "Import2");
        }
        echo '<pre>';
        print_r('完成了');
        exit();
    }

    //批量更新
    public function update_all_doc()
    {
        echo '<pre>';
        print_r("OVER");
        exit();
        // 可以灵活添加新字段,最好不要乱添加
        $params = [
            'index' => $this->index,
            'body' => [
                'script' => 'ctx._source.recommend = 0',
            ],
        ];
        $re = $this->client->updateByQuery($params);

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

    }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值