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

https://www.cnblogs.com/werben/p/11550412.html

一、elasticsearch的Dockerfile

增加中文搜索插件analysis-ik

1
2
3
4
5
6
7
8
9
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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怎样都没有生效(原因没找到),于是直接自己写配置文件,并将配置文件磁盘映射到容器中

1
2
3
4
5
6
7
8
9
10
#
# ** 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

在根目录下引入库

1
composer require elasticsearch/elasticsearch
复制代码
use Elasticsearch\ClientBuilder;


//删除索引下的所有文档
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\n";
    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 "\n";
}

//删除索引
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( "\r\n", "\n\n", "\r", "  "), "", $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;
}
posted @ 2021-09-30 18:02  酷酷的城池  阅读(184)  评论(0编辑  收藏  举报