PHP使用Elasticsearch搜索引擎
注意
PHP使用Elasticsearch搜索引擎实现,要注意Elasticsearch、Elasticsearch-php与php的版本。这里我使用的是Elasticsearch 5.4.1、php 7、Elasticsearch-php5.0
PHP使用Elasticsearch
执行composer require elasticsearch/elasticsearch~5.0
连接Elasticsearch:
public function __construct()
{
//host数组可配置多个节点
$params = [
'http://Elasticsearch服务器ip:9200'
];
$this->es = ClientBuilder::create()->setHosts($params)->build();
}
创建索引
public function es_create(){
$params = [
'index' => 'test', //索引名称
'body' => [
'settings'=> [ //配置
'number_of_shards'=> 3,//主分片数
'number_of_replicas'=> 1 //主分片的副本数
],
'mappings'=> [ //映射
'_default_' => [ //默认配置,每个类型缺省的配置使用默认配置
'_all'=>[ // 关闭所有字段的检索
'enabled' => 'false'
],
'_source'=>[ // 存储原始文档
'enabled' => 'true'
],
'properties'=> [ //配置数据结构与类型
'name'=> [ //字段1
'type'=>'string',//类型 string、integer、float、double、boolean、date
'index'=> 'analyzed',//索引是否精确值 analyzed not_analyzed
],
'age'=> [ //字段2
'type'=>'integer',
],
'sex'=> [ //字段3
'type'=>'string',
'index'=> 'not_analyzed',
],
]
],
'my_type' => [
'properties' => [
'phone'=> [
'type'=>'string',
],
]
],
],
]
];
$res = $this->es->indices()->create($params);
dd($res,1);
}
查看Mappings
public function es_get(){
$params = [
'index' => 'test'
];
$res = $this->es->indices()->getMapping($params);
dd($res);
}
修改Mappings
public function es_set(){
$params = [
'index' => 'test',
'type' => 'my_type',
'body' => [
'my_type' => [
'properties' => [
'idcard' => [
'type' => 'integer'
]
]
]
]
];
$res = $this->es->indices()->putMapping($params);
dd($res);
}
删除索引
public function es_del(){
$params = [
'index' => 'test'
];
$res = $this->es->indices()->delete($params);
dd($res);
}
插入单条 Document
public function postBulkDoc(){
for($i = 0; $i < 5; $i++) {
$params['body'][] = [
'index' => [
'_index' => 'test',
'_type' => 'my_type',
]
];
$params['body'][] = [
'age' => 17+$i,
'name' => 'reimu'.$i,
'sex' => '女性',
'idcard' => 1112+$i,
'phone' => '1245789'.$i,
];
}
$res = $this->es->bulk($params);
dd($res);
}
通过id获取Document
public function getDocById(){
$params = [
'index' => 'test',
'type' => 'my_type',
'id' => 'AX3nTLqXArjzNK3LMPwI'
];
$res = $this->es->get($params);
dd($res);
}
通过id更新Document
public function updateDocById(){
$params = [
'index' => 'test',
'type' => 'my_type',
'id' => 'AX3nTLqXArjzNK3LMPwI',
'body' => [
'doc' => [ //将doc中的文档与现有文档合并
'name' => 'marisa'
]
]
];
$res = $this->es->update($params);
dd($res);
}
通过id删除Document
public function deleteDocById(){
$params = [
'index' => 'test',
'type' => 'my_type',
'id' => 'AX3nTLqXArjzNK3LMPwI'
];
$res = $this->es->delete($params);
dd($res);
}
注意:以上通过id的三个操作,如果未找到id,Elasticsearch-php会直接报错!
搜索Document
public function searchDoc()
{
$params = [
'index' => 'test',
'type' => 'my_type',
'body' => [
'query' => [
'constant_score' => [ //非评分模式执行
'filter' => [ //过滤器,不会计算相关度,速度快
'term' => [ //精确查找,不支持多个条件
'name' => 'reimu1'
]
]
]
]
]
];
$res = $this->es->search($params);
dd($res);
}
扩展
- ES中的搜索分两个概念,
匹配和过滤
匹配通常针对的是字符串 类型的字段,而过滤针通常对的精确的类型
,比如 integer,keyword,date等, 他们之间没有明确的规定
,匹配可以去匹配data,integer等类型,过滤也可以去过滤text字段,通过匹配的方式去找精确类型通常不会出现什么问题,通过过滤去找text类型的数据通常会得到意外的结果。- 如果没有特殊情况,匹配针对text类型,过滤针对其他类型,但是
对于精确类型使用过滤的性能通常比匹配更高,所以能使用过滤的地方都过滤
。 - 要区别一下MySQL中的过滤概念,
MySQL中的过滤是对查找后的数据进行过滤,而在ES中,过滤和匹配都等同于MySQL中的查找,匹配适合查找模糊数据,过滤适合查找精确数据而已
。
常用的过滤
精确查找
$query = [
'query' => [
'term' => [
'name' => 'reimu1'
]
]
];
精确查找多个字段
$query = [
'query' => [
'terms' => [
'name' => [ 'reimu1', 'reimu2']
]
]
];
范围查找
$query = [
'query' => [
'range' => [
'age' => [
'gt' => 15,
'lt' => 25
]
]
]
];
exists(等同于MySQL中的 is not null),查找存在age属性的文档
$query = [
'query' => [
'exists' => [
'field' => 'age'
]
]
];
missing(等同于 MySQL中的 is null)
注意:这个过滤方法在2.x版本就废弃了,请使用 must_not 嵌套 exists 来实现,bool(用来组合其他过滤条件,包含 must,must_not,should操作)
$query = [
'query' => [
'bool' => [
'should' => [
'range' => [
'age' => ['gt' => 20]
]
],
'must_not' => [
'term' => [
'info.sex' => '女性'
]
],
'must' => [
[
'term' => [
'info.idcard' => '114'
]
],
[
'term' => [
'info.phone' => '12457892'
]
]
]
]
]
];
上面这个查询的意思是,年龄大于20,性别不能是女性,idcard是114且电话是12457892。
常用的查询:
match(匹配一个字段)
$query = [
'query' => [
'match' => [
'name' => 'reimu2'
]
]
];
match_all(匹配所有文档,相当于没有条件)
等于是 $query = []
multi_match(匹配多个字段)
$query = [
'query' => [
'multi_match' => [
'query' => '1',
'fields' => ['phone','idcard']
]
]
];
匹配phone和idcard里面包含 '1' 的数据
bool(用来组合其他匹配条件,包含 must,must_not,should操作)
$query = [
'query' => [
'bool' => [
'should' => [
'match' => [
'name' => 'reimu2'
]
],
'must_not' => [
'match' => [
'info.sex' => '女性'
]
]
]
]
];
中文分词
Elasticsearch+ik实现中文分词 ES默认的分词是英文分词,对中文分词支持的并不好。所以需要安装ik中文分词。
猜你喜欢
在 Laravel 中集成 Swoole 实现 WebSocket 服务器
阅读 1046基于 LaravelS 扩展包把 Swoole 集成到 Laravel 项目来实现 WebSocket 服务器,以便与客户端进行 WebSocket 通信从而实现广播功能。
Layui富文本视频等多功能
阅读 788Layui富文本多功能添加
Resultful API规范
阅读 562什么是resultful
PHP定时任务
阅读 514PHP框架Laravel定时任务的实现
php 安装 kafka扩展,laravel使用kafka
阅读 1033php 安装 kafka扩展,laravel使用kafka做订阅消息
php 的swoole 和websocket 连接wss
阅读 753wss的设置
Swoole 扩展安装与使用入门
阅读 475Swoole从入门到实战
redis秒杀
阅读 847基于redis 实现并发情况的超卖超买解决方案