php ElasticSearch父子文档操作

<?php

namespace app\elasticsearch;

use Elasticsearch\Client;
use Elasticsearch\ClientBuilder;
use Elasticsearch\ConnectionPool\StaticNoPingConnectionPool;
use Elasticsearch\ConnectionPool\Selectors\RoundRobinSelector;

// https://www.blsa.cn/articles/201
class ParentChildEs
{
    /** @var Client es连接 */
    private $client;

    private $indexName = 'parent_child';
    private $type = '_doc';

    public function __construct()
    {
        $hosts = [
            'host' => '192.168.213.128'
        ];
        $this->client = ClientBuilder::create()
            // 连接池:维持一份连接清单,它决定节点在什么时候从活节点转变为死节点(或死节点转变为活节点)
            ->setConnectionPool(StaticNoPingConnectionPool::class, [])
            // 选择器:连接池选择连接对象时是没有逻辑的
            ->setSelector(RoundRobinSelector::class)
            ->setHosts($hosts)
            ->build();
    }

    // -------------------------索引mapping
    // 创建索引
    public function create()
    {
        $params = [
            'index' => $this->indexName,
            'body' => [
                'settings' => [
                    'number_of_shards' => 1,    // 分片数
                    'number_of_replicas' => 0,  // 副本数
                    'index' => [    // 设置默认分词器
                        "analysis.analyzer.default.type" => "ik_max_word"
                    ]
                ],
            ]
        ];
        $res = $this->client->indices()->create($params);
    }

    // 1. 设置索引的mapping
    public function setMapping(): void
    {
        $this->create();
        $params = [
            'index' => $this->indexName,
            'type' => $this->type,
            'include_type_name' => true,
            'body' => [
                $this->type => [
                    'properties' => [
                        'company_id' => ['type' => 'keyword'],
                        'name' => ['type' => 'text'],
                        'parent_join' => [
                            'type' => 'join',
                            'relations' => ['parent_company' => 'sub_company']
                        ]
                    ]
                ]
            ]
        ];
        $res = $this->client->indices()->putMapping($params);
        var_dump($res);
    }

    // 2. 插入父文档数据
    public function bulkParent(): void
    {
        $data = [
            [
                'company_id' => '1',
                'name' => '阿里巴巴',
                'parent_join' => ['name' => 'parent_company'],
            ],
            [
                'company_id' => '2',
                'name' => '杭州阿里巴巴',
                'parent_join' => ['name' => 'parent_company'],
            ],
            [
                'company_id' => '3',
                'name' => '小米',
                'parent_join' => ['name' => 'parent_company'],
            ],
            [
                'company_id' => '4',
                'name' => '北京小米',
                'parent_join' => ['name' => 'parent_company'],
            ],
        ];
        $bulk = [];
        foreach ($data as $item) {
            $bulk['body'][] = [
                'index' => [
                    '_index' => $this->indexName,
                    '_type' => '_doc',
                    '_id' => $item['company_id'],
                ]
            ];
            $bulk['body'][] = $item;
        }
        $response = $this->client->bulk($bulk);
        var_dump($response);
        exit;
    }

    // 3. 插入子文档数据
    public function bulkChild(): void
    {
        $data = [
            [
                'patent_name' => '阿里巴巴专利1',
                'time' => 123,
                'parent_join' => ['name' => 'sub_company', 'parent' => 1],
            ],
            [
                'patent_name' => '阿里巴巴专利2',
                'time' => 888,
                'parent_join' => ['name' => 'sub_company', 'parent' => 2],
            ],
            [
                'patent_name' => '小米专利1',
                'time' => 123,
                'parent_join' => ['name' => 'sub_company', 'parent' => 3],
            ],
            [
                'patent_name' => '小米专利1',
                'time' => 888,
                'parent_join' => ['name' => 'sub_company', 'parent' => 4],
            ],
        ];
        $bulk = [];
        foreach ($data as $item) {
            $bulk['body'][] = [
                'index' => [
                    '_index' => $this->indexName,
                    '_type' => '_doc',
                    '_id' => $item['parent_join']['parent'] . '-1',
                    'routing' => $item['parent_join']['parent'],
                ]
            ];
            $bulk['body'][] = $item;
        }
        $response = $this->client->bulk($bulk);
        var_dump($response);
        exit;
    }

    // 父子文档 https://www.elastic.co/guide/en/elasticsearch/guide/master/parent-child.html
    // has_child 查询,返回父文档
    public function hasChild(): void
    {
        $params = [
            'index' => $this->indexName,
            'type' => $this->type,
            'body' => [
                // 查询父文档
                'query' => [
                    'has_child' => [
                        'type' => 'sub_company',
                        'query' => [
                            'match' => ['patent_name' => '小米'],
                        ],
                    ],
                ],
            ],
        ];
        $response = $this->client->search($params);
        var_dump($response);
    }

    // has_parent 查询,返回子文档
    public function hasParent(): void
    {
        $params = [
            'index' => $this->indexName,
            'type' => $this->type,
            'body' => [
                // 查询子文档
                'query' => [
                    'has_parent' => [
                        'parent_type' => 'parent_company',
                        'query' => [
                            'match' => ['name' => '小米'],
                        ],
                    ],
                ],
            ],
        ];
        $response = $this->client->search($params);
        var_dump($response);
    }

    // 查询所有
    public function search()
    {
        $params = [
            'index' => $this->indexName,
            'type' => $this->type,
        ];
        $res = $this->client->search($params);
        var_dump($res);
    }

    // 根据父id查询,不含子文档
    public function byParentId(): void
    {
        $params = [
            'index' => $this->indexName,
            'type' => $this->type,
            'id' => 1,
        ];
        var_dump($this->client->get($params));
    }

    // 复杂bool查询
    public function complexBool(): void
    {
        $params = [
            'index' => $this->indexName,
            'type' => $this->type,
            'body' => [
                'query' => [
                    'bool' => [
                        'must' => [
                            [
                                'has_child' => [
                                    'type' => 'sub_company',
                                    'query' => [
                                        'bool' => [
                                            'must' => [
                                                [
                                                    'range' => [
                                                        'time' => ['gte' => 300, 'lte' => 900]
                                                    ]
                                                ]
                                            ]
                                        ]
                                    ]
                                ]
                            ],
                            [
                                'match' => [
                                    'name' => '阿里巴巴'
                                ]
                            ]
                        ]
                    ]
                ]
            ],
        ];
        var_dump($this->client->search($params));
    }
}