php使用Elasticsearch7进行地理位置搜索

首先使用composer安装elasticsearch composer require elasticsearch/elasticsearch

简单封装ES类, 需要注意es7下取消了type

<?php
namespace app\common\lib;

use Elasticsearch\ClientBuilder;

class Es
{
    private $client;
    // 构造函数
    public function __construct()
    {
        $params = array(
            '127.0.0.1:9200'
        );
        $this->client = ClientBuilder::create()->setHosts($params)->build();
    }

    public function getClient() {
        return $this->client; 
    }
 
    // 创建索引
    public function create_index($index_name = 'meitian', $properties = []) {
        $params  = [
            'index' => $index_name
        ];

        $exists = $this->client->indices()->exists($params);
        if(!$exists) {
            $params['body']['settings']['number_of_shards'] = 5;
            $params['body']['settings']['number_of_replicas'] = 0;
            
            if(!empty($properties)) {
                $params['body']['mappings'] = [
                    '_source' => [
                        'enabled' => true
                    ],
                    'properties' => $properties
                ];
            }

            echo 'create index: '.$index_name;

            $response = $this->client->indices()->create($params);
            return $response;
        }
    }
 
    // 删除索引
    public function delete_index($index_name = 'meitian') {
        $params  = [
            'index' => $index_name
        ];
        $response = $this->client->indices()->delete($params);
        return $response;
    }

    // 添加文档
    public function add_doc($id, $doc, $index_name = 'meitian') {
        $params = [
            'index' => $index_name,
            'id' => $id,
            'body' => $doc
        ];
 
        $response = $this->client->index($params);
        return $response;
    }

    // 批量添加文档
    public function bulk_doc($docs, $index_name = 'meitian') {
        $params = ['body' => []];
        
        $res = 0;
        foreach ($docs as $i => $item) {
            if(!isset($item['id']) || empty($item['id'])) {
                continue;
            }
            $params['body'][] = [
                'index' => [
                    '_index' => $index_name,
                    '_id' => $item['id']
                ],
            ];
            unset($item['id']);
            $params['body'][] = $item;

            if ($i % 1000 == 0) {
                $responses = $this->client->bulk($params);
                $params = ['body' => []];
                unset($responses);
            }

            $res++;

        }

        if (!empty($params['body'])) {
            $responses = $this->client->bulk($params);
        }

        return $res;
    }
 
    // 判断文档存在
    public function exists_doc($id, $index_name = 'meitian') {
        $params = [
            'index' => $index_name,
            'id' => $id
        ];
 
        $response = $this->client->exists($params);
        return $response;
    }
 
 
    // 获取文档
    public function get_doc($id, $index_name = 'meitian') {
        $params = [
            'index' => $index_name,
            'id' => $id
        ];
 
        $response = $this->client->get($params);
        return $response;
    }
 
    // 更新文档
    public function update_doc($id, $doc, $index_name = 'meitian') {
        $params = [
            'index' => $index_name,
            'id' => $id,
            'body' => [
                'doc' => $doc
            ]
        ];
 
        $response = $this->client->update($params);
        return $response;
    }
 
    // 删除文档
    public function delete_doc($id, $index_name = 'meitian') {
        $params = [
            'index' => $index_name,
            'id' => $id
        ];
 
        $response = $this->client->delete($params);
        return $response;
    }
 
    //查看映射
    public function get_mapping($index_name = "meitian") {
        $params = [
            'index' => $index_name,
        ];
        $response = $this->client->indices()->getMapping($params);
        return $response;
    }
}

创建索引

        //实例化ES
    	$es = new Es();

        //创建索引 字段根据实际情况来
        $properties = [
            'user_id' => [
                'type' => 'integer',
            ],
            'name' => [   
                //注意这里用了ik进行了中文分词 文档https://github.com/medcl/elasticsearch-analysis-ik
                "type" => "text",
                "analyzer" => "ik_max_word",
                "search_analyzer" => "ik_smart"
            ],
            'location' => [
                'type' => 'geo_point'   //地理坐标
            ]
        ];
        $res = $es->create_index('store', $properties);

添加文档

        //添加门店数据
        $stores = StoreModel::getAll('id, user_id, name, point_lng, point_lat', []);
        foreach ($stores as $i => &$item) {
            $item['location'] = [
                'lat' => $item['point_lat'],
                'lon' => $item['point_lng']
            ];
            unset($item['point_lat']);
            unset($item['point_lng']);
        }
        $res = $es->bulk_doc($stores, 'store');

搜索文档

        $must = [];
        
        if(!empty($user_id)) {
            $must[] = ['term' => ['user_id' => $user_id]];
        }

        if(!empty($name)) {
            $must[] = ['match' => ['name' => $name]];
        }

        $params = [
            'index' => 'store',
            'from' => 0,
            'size' => 200,    //取200个
            'body' => [
                'query' => [
                    'bool' => [
                        'must' => $must,  //额外筛选条件
                        'filter' => [
                            'geo_distance' => [
                                'distance' => '50km',  //附近50km范围内
                                'location' => [
                                    'lat' => $lat,
                                    'lon' => $lng
                                ]
                            ]
                        ]
                    ]
                ],
                'sort' => [
                    '_geo_distance' => [   //按照距离由近到远排序
                        "unit" => "km",
                        "order" => "asc",
                        "location" => [
                          'lat' => $lat,
                          'lon' => $lng
                        ],
                        "mode" => "min"
                    ]
                ]
            ]
        ];

        
        //实例化Elasticsearch
        $es = new Es();

        //搜索
        $retDoc = $es->getClient()->search($params);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值