枇杷花 發表於 2020-6-23 17:31:00

PHP中使用ElasticSearch

<p>网上很多关于ES的例子都过时了,版本很久,这篇文章的测试环境是ES6.5</p>
<p>通过composer&nbsp;安装</p>
<div class="cnblogs_code">
<pre>composer require 'elasticsearch/elasticsearch'</pre>
</div>
<p>在代码中引入</p>
<div class="cnblogs_code">
<pre>require 'vendor/autoload.php';

use Elasticsearch\ClientBuilder;

$client = ClientBuilder::create()-&gt;setHosts(['172.16.55.53'])-&gt;build();</pre>
</div>
<p>下面循序渐进完成一个简单的添加和搜索的功能。</p>
<p>首先要新建一个&nbsp;index:</p>
<p>index&nbsp;对应关系型数据(以下简称MySQL)里面的数据库,而不是对应MySQL里面的索引,这点要清楚</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><img src="https://common.cnblogs.com/images/copycode.gif"></span></div>
<pre>$params = [
    'index' =&gt; 'myindex', #index的名字不能是大写和下划线开头
    'body' =&gt; [
      'settings' =&gt; [
            'number_of_shards' =&gt; 2,
            'number_of_replicas' =&gt; 0
      ]
    ]
];
$client-&gt;indices()-&gt;create($params);</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><img src="https://common.cnblogs.com/images/copycode.gif"></span></div>
</div>
<p>在MySQL里面,光有了数据库还不行,还需要建立表,ES也是一样的,ES中的type对应MySQL里面的表。</p>
<p>注意:ES6以前,一个index有多个type,就像MySQL中一个数据库有多个表一样自然,但是ES6以后,每个index只允许一个type,在往以后的版本中很可能会取消type。</p>
<p>type不是单独定义的,而是和字段一起定义</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><img src="https://common.cnblogs.com/images/copycode.gif"></span></div>
<pre>$params = [
    'index' =&gt; 'myindex',
    'type' =&gt; 'mytype',
    'body' =&gt; [
      'mytype' =&gt; [
            '_source' =&gt; [
                'enabled' =&gt; true
            ],
            'properties' =&gt; [
                'id' =&gt; [
                  'type' =&gt; 'integer'
                ],
                'first_name' =&gt; [
                  'type' =&gt; 'text',
                  'analyzer' =&gt; 'ik_max_word'
                ],
                'last_name' =&gt; [
                  'type' =&gt; 'text',
                  'analyzer' =&gt; 'ik_max_word'
                ],
                'age' =&gt; [
                  'type' =&gt; 'integer'
                ]
            ]
      ]
    ]
];
$client-&gt;indices()-&gt;putMapping($params);</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><img src="https://common.cnblogs.com/images/copycode.gif"></span></div>
</div>
<p>在定义字段的时候,可以看出每个字段可以定义单独的类型,在first_name中还自定义了&nbsp;分词器 ik,</p>
<p>这个分词器是一个插件,需要单独安装的,参考另一篇文章:ElasticSearch基本尝试</p>
<p>现在&nbsp;数据库和表都有了,可以往里面插入数据了</p>
<p>概念:这里的 数据 在ES中叫&nbsp;文档</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><img src="https://common.cnblogs.com/images/copycode.gif"></span></div>
<pre>$params = [
    'index' =&gt; 'myindex',
    'type' =&gt; 'mytype',
    //'id' =&gt; 1, #可以手动指定id,也可以不指定随机生成
    'body' =&gt; [
      'first_name' =&gt; '张',
      'last_name' =&gt; '三',
      'age' =&gt; 35
    ]
];
$client-&gt;index($params);</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><img src="https://common.cnblogs.com/images/copycode.gif"></span></div>
</div>
<p>多插入一点数据,然后来看看怎么把数据取出来:</p>
<p>通过id取出单条数据:</p>
<p>插曲:如果你之前添加文档的时候没有传入id,ES会随机生成一个id,这个时候怎么通过id查?id是多少都不知道啊。</p>
<p>所以这个插入一个简单的搜索,最简单的,一个搜索条件都不要,返回所有index下所有文档:</p>
<div class="cnblogs_code">
<pre>$data = $client-&gt;search();</pre>
</div>
<p>现在可以去找一找id了,不过你会发现id可能长这样:zU65WWgBVD80YaV8iVMk,不要惊讶,这是ES随机生成的。</p>
<p>现在可以通过id查找指定文档了:</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><img src="https://common.cnblogs.com/images/copycode.gif"></span></div>
<pre>$params = [
    'index' =&gt; 'myindex',
    'type' =&gt; 'mytype',
    'id' =&gt;'zU65WWgBVD80YaV8iVMk'
];
$data = $client-&gt;get($params);</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><img src="https://common.cnblogs.com/images/copycode.gif"></span></div>
</div>
<p>最后一个稍微麻烦点的功能:</p>
<p>注意:这个例子我不打算在此详细解释,看不懂没关系,这篇文章主要的目的是基本用法,并没有涉及到ES的精髓地方,</p>
<p>ES精髓的地方就在于搜索,后面的文章我会继续深入分析</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><img src="https://common.cnblogs.com/images/copycode.gif"></span></div>
<pre>$query = [
    'query' =&gt; [
      'bool' =&gt; [
            'must' =&gt; [
                'match' =&gt; [
                  'first_name' =&gt; '张',
                ]
            ],
            'filter' =&gt; [
                'range' =&gt; [
                  'age' =&gt; ['gt' =&gt; 76]
                ]
            ]
      ]

    ]
];
$params = [
    'index' =&gt; 'myindex',
//'index' =&gt; 'm*', #index 和 type 是可以模糊匹配的,甚至这两个参数都是可选的
    'type' =&gt; 'mytype',
    '_source' =&gt; ['first_name','age'], // 请求指定的字段
    'body' =&gt; array_merge([
      'from' =&gt; 0,
      'size' =&gt; 5
    ],$query)
];
$data = $this-&gt;EsClient-&gt;search($params);</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><img src="https://common.cnblogs.com/images/copycode.gif"></span></div>
</div>
<p>&nbsp;</p>
<p>上面的是一个简单的使用流程,但是不够完整,只讲了添加文档,没有说怎么删除文档,</p>
<p>下面我贴出完整的测试代码,基于Laravel环境,当然环境只影响运行,不影响理解,包含基本的常用操作:</p>
<p>      </p>
<p>&lt;?php</p>
<p>use Elasticsearch\ClientBuilder;<br>use Faker\Generator as Faker;</p>
<p>/**<br> * ES 的 php 实测代码<br> */<br>class EsDemo<br>{<br>    private $EsClient = null;<br>    private $faker = null;<br>    /**<br>   * 为了简化测试,本测试默认只操作一个Index,一个Type,<br>   * 所以这里固定为 megacorp和employee<br>   */<br>    private $index = 'megacorp';<br>    private $type = 'employee';<br>    public function __construct(Faker $faker)<br>    {<br>      /**<br>         * 实例化 ES 客户端<br>         */<br>      $this-&gt;EsClient = ClientBuilder::create()-&gt;setHosts(['172.16.55.53'])-&gt;build();<br>      /**<br>         * 这是一个数据生成库,详细信息可以参考网络<br>         */<br>      $this-&gt;faker = $faker;<br>    }<br>    <br>    /**<br>   * 批量生成文档<br>   * @param $num<br>   */<br>    public function generateDoc($num = 100) {<br>      foreach (range(1,$num) as $item) {<br>            $this-&gt;putDoc([<br>                'first_name' =&gt; $this-&gt;faker-&gt;name,<br>                'last_name' =&gt; $this-&gt;faker-&gt;name,<br>                'age' =&gt; $this-&gt;faker-&gt;numberBetween(20,80)<br>            ]);<br>      }<br>    }<br>    /**<br>   * 删除一个文档<br>   * @param $id<br>   * @return array<br>   */<br>    public function delDoc($id) {<br>      $params = [<br>            'index' =&gt; $this-&gt;index,<br>            'type' =&gt; $this-&gt;type,<br>            'id' =&gt;$id<br>      ];<br>      return $this-&gt;EsClient-&gt;delete($params);<br>    }<br>    /**<br>   * 搜索文档,query是查询条件<br>   * @param array $query<br>   * @param int $from<br>   * @param int $size<br>   * @return array<br>   */<br>    public function search($query = [], $from = 0, $size = 5) {<br>//      $query = [<br>//            'query' =&gt; [<br>//                'bool' =&gt; [<br>//                  'must' =&gt; [<br>//                        'match' =&gt; [<br>//                            'first_name' =&gt; 'Cronin',<br>//                        ]<br>//                  ],<br>//                  'filter' =&gt; [<br>//                        'range' =&gt; [<br>//                            'age' =&gt; ['gt' =&gt; 76]<br>//                        ]<br>//                  ]<br>//                ]<br>//<br>//            ]<br>//      ];<br>      $params = [<br>            'index' =&gt; $this-&gt;index,<br>//            'index' =&gt; 'm*', #index 和 type 是可以模糊匹配的,甚至这两个参数都是可选的<br>            'type' =&gt; $this-&gt;type,<br>            '_source' =&gt; ['first_name','age'], // 请求指定的字段<br>            'body' =&gt; array_merge([<br>                'from' =&gt; $from,<br>                'size' =&gt; $size<br>            ],$query)<br>      ];<br>      return $this-&gt;EsClient-&gt;search($params);<br>    }</p>
<p>    /**<br>   * 一次获取多个文档<br>   * @param $ids<br>   * @return array<br>   */<br>    public function getDocs($ids) {<br>      $params = [<br>            'index' =&gt; $this-&gt;index,<br>            'type' =&gt; $this-&gt;type,<br>            'body' =&gt; ['ids' =&gt; $ids]<br>      ];<br>      return $this-&gt;EsClient-&gt;mget($params);<br>    }</p>
<p>    /**<br>   * 获取单个文档<br>   * @param $id<br>   * @return array<br>   */<br>    public function getDoc($id) {<br>      $params = [<br>            'index' =&gt; $this-&gt;index,<br>            'type' =&gt; $this-&gt;type,<br>            'id' =&gt;$id<br>      ];<br>      return $this-&gt;EsClient-&gt;get($params);<br>    }</p>
<p>    /**<br>   * 更新一个文档<br>   * @param $id<br>   * @return array<br>   */<br>    public function updateDoc($id) {<br>      $params = [<br>            'index' =&gt; $this-&gt;index,<br>            'type' =&gt; $this-&gt;type,<br>            'id' =&gt;$id,<br>            'body' =&gt; [<br>                'doc' =&gt; [<br>                  'first_name' =&gt; '张',<br>                  'last_name' =&gt; '三',<br>                  'age' =&gt; 99<br>                ]<br>            ]<br>      ];<br>      return $this-&gt;EsClient-&gt;update($params);<br>    }</p>
<p>    /**<br>   * 添加一个文档到 Index 的Type中<br>   * @param array $body<br>   * @return void<br>   */<br>    public function putDoc($body = []) {<br>      $params = [<br>            'index' =&gt; $this-&gt;index,<br>            'type' =&gt; $this-&gt;type,<br>//            'id' =&gt; 1, #可以手动指定id,也可以不指定随机生成<br>            'body' =&gt; $body<br>      ];<br>      $this-&gt;EsClient-&gt;index($params);<br>    }<br>    /**<br>   * 删除所有的 Index<br>   */<br>    public function delAllIndex() {<br>      $indexList = $this-&gt;esStatus()['indices'];<br>      foreach ($indexList as $item =&gt; $index) {<br>            $this-&gt;delIndex();<br>      }<br>    }<br>    /**<br>   * 获取 ES 的状态信息,包括index 列表<br>   * @return array<br>   */<br>    public function esStatus() {<br>      return $this-&gt;EsClient-&gt;indices()-&gt;stats();<br>    }</p>
<p>    /**<br>   * 创建一个索引 Index (非关系型数据库里面那个索引,而是关系型数据里面的数据库的意思)<br>   * @return void<br>   */<br>    public function createIndex() {<br>      $this-&gt;delIndex();<br>      $params = [<br>            'index' =&gt; $this-&gt;index,<br>            'body' =&gt; [<br>                'settings' =&gt; [<br>                  'number_of_shards' =&gt; 2,<br>                  'number_of_replicas' =&gt; 0<br>                ]<br>            ]<br>      ];<br>      $this-&gt;EsClient-&gt;indices()-&gt;create($params);<br>    }</p>
<p>    /**<br>   * 检查Index 是否存在<br>   * @return bool<br>   */<br>    public function checkIndexExists() {<br>      $params = [<br>            'index' =&gt; $this-&gt;index<br>      ];<br>      return $this-&gt;EsClient-&gt;indices()-&gt;exists($params);<br>    }</p>
<p>    /**<br>   * 删除一个Index<br>   * @return void<br>   */<br>    public function delIndex() {<br>      $params = [<br>            'index' =&gt; $this-&gt;index<br>      ];<br>      if ($this-&gt;checkIndexExists()) {<br>            $this-&gt;EsClient-&gt;indices()-&gt;delete($params);<br>      }<br>    }</p>
<p>    /**<br>   * 获取Index的文档模板信息<br>   * @return array<br>   */<br>    public function getMapping() {<br>      $params = [<br>            'index' =&gt; $this-&gt;index<br>      ];<br>      return $this-&gt;EsClient-&gt;indices()-&gt;getMapping($params);<br>    }</p>
<p>    /**<br>   * 创建文档模板<br>   * @return void<br>   */<br>    public function createMapping() {<br>      $this-&gt;createIndex();<br>      $params = [<br>            'index' =&gt; $this-&gt;index,<br>            'type' =&gt; $this-&gt;type,<br>            'body' =&gt; [<br>                $this-&gt;type =&gt; [<br>                  '_source' =&gt; [<br>                        'enabled' =&gt; true<br>                  ],<br>                  'properties' =&gt; [<br>                        'id' =&gt; [<br>                            'type' =&gt; 'integer'<br>                        ],<br>                        'first_name' =&gt; [<br>                            'type' =&gt; 'text',<br>                            'analyzer' =&gt; 'ik_max_word'<br>                        ],<br>                        'last_name' =&gt; [<br>                            'type' =&gt; 'text',<br>                            'analyzer' =&gt; 'ik_max_word'<br>                        ],<br>                        'age' =&gt; [<br>                            'type' =&gt; 'integer'<br>                        ]<br>                  ]<br>                ]<br>            ]<br>      ];<br>      $this-&gt;EsClient-&gt;indices()-&gt;putMapping($params);<br>      $this-&gt;generateDoc();<br>    }</p>
<p>}</p><br><br>
来源:https://www.cnblogs.com/liliuguang/p/13183359.html
頁: [1]
查看完整版本: PHP中使用ElasticSearch