• docker-compose搭建elasticsearch+kibana环境,以及php使用elasticsearch


    一、elasticsearch的Dockerfile

    增加中文搜索插件analysis-ik

    FROM docker.elastic.co/elasticsearch/elasticsearch:7.2.0
     
    ENV VERSION=7.2.0
     
    # https://github.com/medcl/elasticsearch-analysis-ik/releases
    ADD https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v${VERSION}/elasticsearch-analysis-ik-$VERSION.zip /tmp/
    RUN /usr/share/elasticsearch/bin/elasticsearch-plugin install -b file:///tmp/elasticsearch-analysis-ik-$VERSION.zip
     
    RUN rm -rf /tmp/*
    

    二、编写docker-compose.yml

    version: '3'
    services:
      es01:
        image: "beng/es:7.2.0"
        build: .
        container_name: es01
        restart: always
        volumes:
          - ./es01/data:/usr/share/elasticsearch/data:rw
          - ./es01/logs:/user/share/elasticsearch/logs:rw
        environment:
          - node.name=es01
          - cluster.name=docker-cluster
          - bootstrap.memory_lock=true
          - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
          - discovery.seed_hosts=es02:9300,es03:9300
          - cluster.initial_master_nodes=es01,es02,es03
        ulimits:
          memlock:
            soft: -1
            hard: -1
        ports:
          - "9200:9200"
          - "9300:9300"
        networks:
          - esnet
     
      es02:
        image: "beng/es:7.2.0"
        build: .
        container_name: es02
        restart: always
        volumes:
           - ./es02/data:/usr/share/elasticsearch/data:rw
           - ./es02/logs:/user/share/elasticsearch/logs:rw
        environment:
          - node.name=es02
          - cluster.name=docker-cluster
          - bootstrap.memory_lock=true
          - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
          - discovery.seed_hosts=es01:9300,es03:9300
          - cluster.initial_master_nodes=es01,es02,es03
        ulimits:
          memlock:
            soft: -1
            hard: -1
        networks:
          - esnet
     
      es03:
        image: "beng/es:7.2.0"
        build: .
        container_name: es03
        restart: always
        volumes:
          - ./es03/data:/usr/share/elasticsearch/data:rw
          - ./es03/logs:/user/share/elasticsearch/logs:rw
        environment:
          - node.name=es03
          - cluster.name=docker-cluster
          - bootstrap.memory_lock=true
          - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
          - discovery.seed_hosts=es01:9300,es02:9300
          - cluster.initial_master_nodes=es01,es02,es03
        ulimits:
          memlock:
            soft: -1
            hard: -1
        networks:
          - esnet
     
      kibana:
        image: docker.elastic.co/kibana/kibana:7.2.0
        container_name: kibana
        ports:
          - 5601:5601
        volumes:
          - ./kibana/kibana.yml:/usr/share/kibana/config/kibana.yml:rw
        networks:
          - esnet
          
    networks:
      esnet:
    

      

    三、编写kibana配置文件

    看到网上很多人将elasticsearch.hosts这些参数直接配置在docker-compose文件里设置environment里面,

    但是我在docker-compose文件里设置environment怎样都没有生效(原因没找到),于是直接自己写配置文件,并将配置文件磁盘映射到容器中

    #
    # ** THIS IS AN AUTO-GENERATED FILE **
    #
     
    # Default Kibana configuration for docker target
    server.name: kibana
    server.host: "0"
    elasticsearch.hosts: [ "http://es01:9200" ]
    xpack.monitoring.ui.container.elasticsearch.enabled: true
    i18n.locale: zh-CN

    四、在php中使用elasticsearch

    composer elasticsearch php库地址:https://packagist.org/packages/elasticsearch/elasticsearch

    elasticsearch php的官方文档参考:https://www.elastic.co/guide/cn/elasticsearch/php/current/_quickstart.html

    在根目录下引入库

    composer require elasticsearch/elasticsearch
    use ElasticsearchClientBuilder;
    
    
    //删除索引下的所有文档
    private function deleteAllDoc() {
        $client = ClientBuilder::create()
            ->setHosts(config('api.elasticsearch_host'))
            ->build();
    
        $params = [
            'index' => 'book',
            'type' => '_doc',
            'body' => [
                'query' => [
                    'bool' => [
                        'must_not' => ['term' => [ 'id' => -1000 ]],
                    ]
                ]
            ]
        ];
    
        $response = $client->deleteByQuery($params);
        echo "delete success
    ";
        print_r($response);
    }
    
    //删除某一个文档
    private function deleteDoc($id = 0) {
        $client = ClientBuilder::create()
            ->setHosts(config('api.elasticsearch_host'))
            ->build();
    
        $params = [
            'index' => 'book',
            'type' => '_doc',
            'id' => $id
        ];
    
        $response = $client->delete($params);
        print_r($response);
    }
    
    //获取文档
    private function getDoc($id = 0) {
    
        $client = ClientBuilder::create()
            ->setHosts(config('api.elasticsearch_host'))
            ->build();
    
        $params = [
            'index' => 'book_index',
            'type' => '_doc',
            'id' => $id
        ];
    
        try {
            $response = $client->get($params);
            print_r($response['_source']);
        } catch (Missing404Exception $e) {
            echo 'not exist!';
        }
    }
    
    //添加文档
    private function addDoc() {
        $client = ClientBuilder::create()
            ->setHosts(config('api.elasticsearch_host'))
            ->build();
        $params = [
            'index' => 'my_index',
            'type' => '_doc',
            'id' => strval(2),
            'body' => [
                'first_name' => '关 搜键隔字,以英逗索用号分,书本标文签用label字,不要段混淆',
                'age' => 18
            ]
        ];
        $response = $client->index($params);
        print_r($response);
        print "
    ";
    }
    
    //删除索引
    private function deleteIndex() {
        $client = ClientBuilder::create()
            ->setHosts(config('api.elasticsearch_host'))
            ->build();
    
        $params = ['index' => 'book'];
        $response = $client->indices()->delete($params);
        print_r($response);
    }
    
    //创建索引
    private function createIndex() {
    
        $client = ClientBuilder::create()
            ->setHosts(config('api.elasticsearch_host'))
            ->build();
    
        $params = [
            'index' => 'book_index',
            'body' => [
                'settings' => [
                    'number_of_shards' => 2,
                    'number_of_replicas' => 1
                ],
                'mappings' => [
                    '_source' => [
                        'enabled' => true
                    ],
                    'properties' => [
                        'id' => [
                            'type' => 'integer',
                        ],
                        'title' => [
                            'type' => 'text',
                            //使用ik中文分词
                            'analyzer' => 'ik_max_word'
                        ],
                        'image' => [
                            'type' => 'text'
                        ],
                        'author' => [
                            'type' => 'text',
                            'analyzer' => 'ik_max_word'
                        ],
                        'words' => [
                            'type' => 'integer'
                        ],
                        'description' => [
                            'type' => 'text',
                            'analyzer' => 'ik_max_word'
                        ],
                        'is_vip' => [
                            'type' => 'integer'
                        ],
                        'bookstatus' => [
                            'type' => 'text'
                        ],
                        'online_status' => [
                            'type' => 'integer'
                        ],
                        'type_name' => [
                            'type' => 'text'
                        ],
                        'heat' => [
                            'type' => 'integer'
                        ],
                        'stars' => [
                            'type' => 'float'
                        ],
                    ]
                ]
            ]
        ];
    
        $response = $client->indices()->create($params);
        print_r($response);
    }
    
    
    
    //搜索书籍
    public function searchBook($key, $vip = 0, $page = 1) {
    
        $size = 20;
        $words_size = 30;
        $match_num = 2;
        $offset = ($page - 1) * $size;
        
        $client = ClientBuilder::create()
            ->setHosts(config('api.elasticsearch_host'))
            ->build();
        
        //插入到高亮搜索字前面的内容
        $pre_tags = "";
        //插入到高亮搜索字后面的内容
        $post_tags = "";
        $title_weight = 20;
        $author_weight = 20;
        $description_weight = 1;
        
        $params = [
            'index' => 'book_index',
            'type' => '_doc',
            //分页
            "from" => $offset,
            "size" => $size,
            'body' => [
                'query' => [
                    'bool' => [
                        //其他必须条件,书的vip
                        'must' => ['term' => [ 'is_vip' => intval($vip) ]],
                        //其他必须条件,书的状态必须为已上架
                        'must' => ['term' => [ 'online_status' => 5 ]],
                        //撞击分数规则
                        'should' => [
                            'multi_match' => [
                                //搜索关键字
                                'query' => $key,
                                //书的标题权重20,书的作者标题权重20,书简述权重为1
                                'fields' => ['title^'.$title_weight, 'author^'.$author_weight, 'description^'.$description_weight],
                                "type" => "cross_fields",
                                "operator" => "OR",
                                //至少匹配度30%
                                "minimum_should_match" => "30%"
                            ]
                        ]
                    ]
                ],
                //关键字高亮
                'highlight' => [
                    //匹配包含关键字的高亮次数,比如有30段文本包含关键字,如果只需要前面两次的,那$match_num=2
                    'number_of_fragments' => $match_num,
                    //匹配包含关键字的高亮段落保留多少文字,比如一片文章中有30个片段包含关键字,
                    //每个片段保留30个文字,则$words_size=30,多余的会忽略
                    'fragment_size' => $words_size,
                    'fields' => [
                        //高亮的字段,这里高亮书的标题和作者以及书简述
                        'title' => ['pre_tags' => $pre_tags, 'post_tags' => $post_tags,],
                        'author' => ['pre_tags' => $pre_tags, 'post_tags' => $post_tags,],
                        'description' => ['pre_tags' => $pre_tags, 'post_tags' => $post_tags,],
                    ]
                ]
            ]
        ];
        
        $results = $client->search($params);
        $hits = $results['hits']['hits'];
        
        if (empty($results['hits']['hits'])) {
            return [];
        }
        
        $books = [];
        //提取书信息
        foreach ($hits as $key => $value) {
            $book = [];
            $book['book_id'] = $value['_source']['id'];
        
            if (!empty($value['highlight']['title'])) {
                $book['title'] = $value['highlight']['title'][0];
            } else {
                $book['title'] = $value['_source']['title'];
            }
        
            if (!empty($value['highlight']['author'])) {
                $book['author'] = $value['highlight']['author'][0];
            } else {
                $book['author'] = $value['_source']['author'];
            }
        
            if (!empty($value['highlight']['description'])) {
                $book['description'] = $value['highlight']['description'][0];
        
                if (!empty($value['highlight']['description'][1])) {
                    $book['description'] = $book['description']. '...' .$value['highlight']['description'][1];
                }
            } else {
                $book['description'] = $value['_source']['description'];
            }
            $book['description'] = str_replace(array( "
    ", "
    
    ", "
    ", "  "), "", $book['description']);
        
            $book['bookstatus'] = $value['_source']['bookstatus'];
            $book['image'] = $value['_source']['image'];
            $book['words'] = $value['_source']['words'];
            $book['stars'] = $value['_source']['stars'];
            $book['heat'] = $value['_source']['heat'];
            $book['type_name'] = $value['_source']['type_name'];
            array_push($books, $book);
        }
        
        return $books;
    }
  • 相关阅读:
    JAVA中堆和栈的区别
    怎么回答面试官:你对Spring的理解?
    如何设计一个高可用、高并发秒杀系统
    这应该是把Java内存区域讲的最清楚的一篇文章
    Spring Cloud底层原理解析
    Spring事务管理详解
    选择合适Redis数据结构,减少80%的内存占用
    最强Java并发编程详解:知识点梳理,BAT面试题等
    深入理解HashMap
    Springboot 优雅停止服务的几种方法
  • 原文地址:https://www.cnblogs.com/werben/p/11550412.html
Copyright © 2020-2023  润新知