由网络副手--寻路人于2017.08.31 19:20:00发布在NoSql技术 ElasticSearch+PHP 实战 阅读3776 评论0 喜欢0 一、项目背景: 我们要做一个项目,此项目包含字、词、成语、诗句,可供给用户查询. 我们分析出来一批用的常规需求。 比如用户搜索 “好”怎么读 与“乐同音”的字、同笔画得字. 写“荷花”的诗有哪些? 这些分析无非就是要根据query 来分析出查询条件. 是完全匹配,还是包含,是条件中并列,还有排序等等问题. 二、为什么选择ElasticSearch 这个技术. 2.1 搜索维度多、而且是汉子、而且需要支持分词、排序 速度要快 2.2 分布式存储、性能快、丰富的API 2.3 通俗的数据结构,JSON即可 三、技术文档 官方API文档:如果英文好建议直接阅读英文文档,中午的文档很早了,现在最新的5.5 版本。 中文版文档有问题,尤其在结构化查询中的过滤查询,结构错误,等等。 https://www.elastic.co/guide/index.html 说下ES中词概念和传统DB的关联性 MYSQL -> DATABASE -> TABLE -> FIELD ES -> INDEX -> TYPE -> FIELD 四、应用场景以及代码块 ----------------------------------------------------------------------------------------- API 引用模块 直接看对应的API Client 模块,选择对应的包 ------------------------------------------------------------------------------------------ 1. 可以通过composer 下载elasticsearch PHP 类库 2. 引入后实例化 一、创建连接 如果$hosts 不设置,则默认访问localhost:9200 端口. HOST里的条目对应集群中Node节点 $hosts = [ '192.168.1.1:9200', // IP + Port '192.168.1.2', // Just IP 'mydomain.server.com:9201', // Domain + Port 'mydomain2.server.com', // Just Domain 'https://localhost', // SSL to localhost 'https://192.168.1.3:9200' // SSL to IP + Port ]; //对于有密码的情况下 $hosts = [ // This is effectively equal to: "https://username:password!#$?*abc@foo.com:9200/" [ 'host' => 'foo.com', 'port' => '9200', 'scheme' => 'https', 'user' => 'username', 'pass' => 'password!#$?*abc' ], // This is equal to "http://localhost:9200/" [ 'host' => 'localhost', // Only host is required ] ]; try{ $this->client = \Elasticsearch\ClientBuilder::create()->setHosts($hosts)->build(); }catch (Elasticsearch\Common\Exceptions\Curl\CouldNotConnectToHost $e) { $previous = $e->getPrevious(); if ($previous instanceof 'Elasticsearch\Common\Exceptions\MaxRetriesException') { echo "Max retries!"; } } 二、执行程序语句 这说一句,ES执行的代码命令,底层都是JSON结构化数据。在PHP API 中展示的看起啦都是数组格式,实际上在类库文件中最终处理的时候会做一层转换 2.1 创建索引 $client = ClientBuilder::create()->build(); $params = [ 'index' => 'my_index', 'body' => [ 'settings' => [ 'number_of_shards' => 3, 'number_of_replicas' => 2 ], 'mappings' => [ 'my_type' => [ '_source' => [ 'enabled' => true ], 'properties' => [ "title" => [ "type" => "text", "fields" => [ "keyword" => [ "type" => "keyword", //如此可以根据title.keyword进行精确查询 "ignore_above" => 256 ] ] ], 'first_name' => [ 'type' => 'string', 'analyzer' => 'standard' ], 'age' => [ 'type' => 'integer' ] ] ] ] ] ]; // Create the index with mappings and settings now $response = $client->indices()->create($params); 2.2 删除索引 $deleteParams = [ 'index' => '索引名' //这里注意,删除后你的整个库就没了,去留自己选择,相当于drop database 数据库名 ]; $response = $client->indices()->delete($deleteParams); print_r($response); 2.3 增 创建条数据字段testField 的值 为 abc. $params = [ 'index' => 'my_index', 'type' => 'my_type', 'body' => [ 'testField' => 'abc'] ]; $response = $client->index($params); 2.4.删 2.4.1 根据ID删除 $params = [ 'index' => 'my_index', //索引名 即数据库名 'type' => 'my_type', //type 即表明 'id' => '_id' //id 即字段ID,如果自己不做设置,ES会为我们生成一个字段 ]; $response = $client->delete($params); print_r($response); 2.5.改 需要先知道数据的ID,然后根据ID进行修改 2.5.1 文档字段修改 $params = [ 'index'=>'test', 'type'=>'test', 'id' => 'id', 'body' => array{ "query": { "doc": { "字段" : "值" //用doc来指定修改的数据结构体 } } ] 2.5.2 针对某个字段修改的同时还需要增加新属性 $params = [ 'index' => 'my_index', 'type' => 'my_type', 'id' => 'my_id', 'body' => [ 'script' => 'ctx._source.counter += count', 'params' => [ 'count' => 4 ] ] ]; 2.5.3 有则更新无则插入字段,upsert 来做处理 $params = [ 'index' => 'my_index', 'type' => 'my_type', 'id' => 'my_id', 'body' => [ 'script' => 'ctx._source.counter += count', 'params' => [ 'count' => 4 ], 'upsert' => [ //upsert 来做处理 'counter' => 1 ] ] ]; 2.6 查 2.6.1 根据ID 查询 $ params = [ 'index'=>'test', 'type'=>'test', 'id'=> 1 ]。 $ response = $client-> get($ params); 2.6.2 根据某个字段匹配 1. 查询title=好数据 $params = [ 'index'=>'test', 'type'=>'test', 'body' => array{ "query": { "match": { "title.keyword" : "好" //如果想查询包含好的字,就把keyword去掉 } } ] 2.6.3 根据某两个字段匹配并排序 注释: 查询spell字段下面simple_shape 读音为好,并且spell下voice 声调是4的,并按照热度倒序,取出2条 通俗点,取出2个同音字 $params = [ 'index'=>'test', 'type'=>'test', 'body' => array{ "query": { "bool": { "must": [ { "match": { "spell.simple_shape": "hao" }}, { "match": { "spell.voice": "4" }} ] } }, "sort": [ { "hot.keyword": { "order": "desc" } } ], "from": 0, "size": 2 } ] 用以上代码足够创建一个简单的小型搜索项目了,多数数据都从上面演化而来,有更复杂的查询和原理,咱们后面再聊.~~ 赞 0 分享 赏 您可以选择一种方式赞助本站 支付宝扫码赞助 BraveDu 署名: 网络副手~寻路人