php操作elasticsearch8

        ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。        

        官网:https://www.elastic.co/cn/

        文档:https://www.elastic.co/guide/cn/elasticsearch/php/current/_overview.html

                  https://www.elastic.co/cn/virtual-events/getting-started-elasticsearch

        Elasticsearch Clients:https://www.elastic.co/guide/en/elasticsearch/client/index.html

    

        ElasticSearch学习4--复杂查询


        other:

                纳速云


        如果未指定主机,客户端将尝试连接到localhost:9200.        

        主机配置

$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
];
$client = ClientBuilder::create()           // Instantiate a new ClientBuilder
                    ->setHosts($hosts)      // Set the hosts
                    ->build();              // Build the client object


        使用 composer require 'elasticsearch/elasticsearch' 来下载到自己项目里

[root@bogon ~]# /usr/local/nginx/html
[root@bogon html]# chmod -R 777 www.es.com/
[root@bogon html]# su cc
[cc@bogon html]$ cd www.es.com/
[cc@bogon www.es.com]$ composer require 'elasticsearch/elasticsearch'
[cc@bogon www.es.com]# ls
composer.json  composer.lock  vendor

      


    1、创建索引文档

<?php
require 'vendor/autoload.php';

$client = Elastic\Elasticsearch\ClientBuilder::create()->build();
$params = [ 'index' => 'test_index' , 'id' => 'my_id' , 'body' => [ 'testField' => 'abc' ] ]; 
$response = $client->index($params);

echo "<pre>";
print_r($response->asArray());

# 输出结果:
[root@bogon www.es.com]# php test.php 
<pre>Array
(
    [_index] => test_index
    [_id] => my_id3
    [_version] => 2
    [result] => updated
    [_shards] => Array
        (
            [total] => 1
            [successful] => 1
            [failed] => 0
        )

    [_seq_no] => 3
    [_primary_term] => 1
)

        2、查看当前 test_index 索引所有文档

[root@bogon www.es.com]# curl http://localhost:9200/_cat/indices?v        #类似mysql的show tables
health status index      uuid                   pri rep docs.count docs.deleted store.size pri.store.size dataset.size
green  open   test_index 9a_38WOAQSO3IFx2CO71Uw   1   0          4            0       14kb           14kb         14kb
[root@bogon www.es.com]# curl -X GET "http://localhost:9200/test_index/_search?pretty=true"
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "test_index",
        "_id" : "my_id",
        "_score" : 1.0,
        "_source" : {
          "testField" : "abc"
        }
      },
      {
        "_index" : "test_index",
        "_id" : "my_id3",
        "_score" : 1.0,
        "_source" : {
          "testField" : "abd"
        }
      },
      {
        "_index" : "test_index",
        "_id" : "my_id2",
        "_score" : 1.0,
        "_source" : {
          "testField" : "edf"
        }
      },
      {
        "_index" : "test_index",
        "_id" : "my_id4",
        "_score" : 1.0,
        "_source" : {
          "testField" : "asdfg"
        }
      }
    ]
  }
}

        

        3、获取文档

        让我们获取刚刚索引的文档。

<?php
require 'vendor/autoload.php';

$client = Elastic\Elasticsearch\ClientBuilder::create()->build();
$params = [ 'index' => 'test_index' , 'id' => 'my_id4' ]; 
$response = $client->get($params);

echo "<pre>";
print_r($response->asArray());

# 输出结果:
[root@bogon www.es.com]# php test.php 
<pre>Array
(
    [_index] => test_index
    [_id] => my_id4
    [_version] => 1
    [_seq_no] => 4
    [_primary_term] => 1
    [found] => 1
    [_source] => Array
        (
            [testField] => asdfg
        )

)

        4、搜索文档

<?php
require 'vendor/autoload.php';

$client = Elastic\Elasticsearch\ClientBuilder::create()->build();
$params = [
    'index' => 'test_index',
    'body'  => [
        'query' => [
            'match' => [
                'testField' => 'abc'
            ]
        ]
    ]
];
$response = $client->search($params);

echo "<pre>";
print_r($response->asArray());


输出结果:
[root@bogon www.es.com]# php test.php 
<pre>Array
(
    [took] => 109
    [timed_out] => 
    [_shards] => Array
        (
            [total] => 1
            [successful] => 1
            [skipped] => 0
            [failed] => 0
        )

    [hits] => Array
        (
            [total] => Array
                (
                    [value] => 1
                    [relation] => eq
                )

            [max_score] => 1.2039728
            [hits] => Array
                (
                    [0] => Array
                        (
                            [_index] => test_index
                            [_id] => my_id
                            [_score] => 1.2039728
                            [_source] => Array
                                (
                                    [testField] => abc
                                )

                        )

                )

        )

)

        5、删除文档

<?php
require 'vendor/autoload.php';

$client = Elastic\Elasticsearch\ClientBuilder::create()->build();
$params = [ 'index' => 'test_index' , 'id' => 'my_id' ]; 
$response = $client->delete($params);

echo "<pre>";
print_r($response->asArray());


# 输出结果
[root@bogon www.es.com]# php test.php 
<pre>Array
(
    [_index] => test_index
    [_id] => my_id
    [_version] => 2
    [result] => deleted
    [_shards] => Array
        (
            [total] => 1
            [successful] => 1
            [failed] => 0
        )

    [_seq_no] => 5
    [_primary_term] => 1
)

        6、删除索引

<?php
require 'vendor/autoload.php';

$client = Elastic\Elasticsearch\ClientBuilder::create()->build();

$deleteParams = [
    'index' => 'test_index'
];
$response = $client->indices()->delete($deleteParams);

echo "<pre>";
print_r($response->asArray());

# 输出结果:
[root@bogon www.es.com]# php test.php 
<pre>Array
(
    [acknowledged] => 1
)

#再次执行  curl  test_index 索引

        7、创建索引

<?php
require 'vendor/autoload.php';

$client = Elastic\Elasticsearch\ClientBuilder::create()->build();

$params = [
    'index' => 'test_index',
    'body' => [
        'settings' => [
            'number_of_shards' => 2,
            'number_of_replicas' => 0
        ]
    ]
];

$response = $client->indices()->create($params);

echo "<pre>";
print_r($response->asArray());

# 输出结果
[root@bogon www.es.com]# php test.php 
<pre>Array
(
    [acknowledged] => 1
    [shards_acknowledged] => 1
    [index] => test_index
)

        8、文档排序

require 'vendor/autoload.php';

$client = Elastic\Elasticsearch\ClientBuilder::create()->build();


$params = [
    'index' => 'user',
    'body'  => [
        'query' => [
            'match' => [
                'username' => 'ck'
            ]
        ],
	'sort' => [  
       	    'age' => [
                'order' => 'desc'
            ]
    	]
    ]
];
$response = $client->search($params);

echo "<pre>";
print_r($response->asArray());





        单点 ,创建索引时 es 报错:current.health="RED" message="Cluster health status changed from [YELLOW] to [RED] (reason: [reconcile-desired-balance])." previous.health="YELLOW" reason="reconcile-desired-balance"。


        查看es的健康状态http://192.168.241.142:9200/_cat/health?v status是红色。

        http://192.168.241.142:9200/_cat/shards  , 可以看到某些索引对应的分片是UNASSIGNED(未分片)状态。经多方百度,得到解决方案:

        修改索引settings的number_of_replicas为0即可。 原因:分片太多,节点不够。单机es,1个节点但分片的副本数超过1个了,每个主分片的副本数少于群集中的节点数,所以要调整为0。

[root@bogon www.es.com]$ curl -XPUT http://192.168.241.142:9200/_settings?pretty -d "{ \"index\": { \"number_of_replicas\": 0 } }" -H "Content-Type: application/json"
{
  "acknowledged" : true
}

        刷新 es健康状态,status 变成green.





        mysql数据批量导入到elasticsearch

        PHP操作es文档位置:https://www.elastic.co/guide/cn/elasticsearch/php/current/_indexing_documents.html

        我数据库里面有1378W条数据,需要插入到elasticsearch

        jvm.options的配置:-Xms1g   -Xmx1g只给了1GB内存,数据库还是用的mysql5.5机械盘,还固态盘的话估计会快一点.

        每次从数据库读取3W条数据,然后插入到elasticsearch,从数据库获取数据到插入到elasticsearch,其中获取3W条数据大约是0.5-0.7秒一次,获取数据+插入到elasticsearch的平均是2.5W条/秒

/**
     * mysql数据批量插入数据到elasticsearch written:yangxingyi
     * 文档位置:https://www.elastic.co/guide/cn/elasticsearch/php/current/_indexing_documents.html
     */
    public function mysql2esAction(){
        ini_set("memory_limit","4048M");
        $start = time();
        $hosts = [
            'http://elastic:changeme@localhost:9200',
        ];
        $client = ClientBuilder::create()->setHosts($hosts)->build();
 
        //从mysql获取数据
        $field = "ID_CDKEY_ORDER,PRODUCTS_NAME,STAMP,EMAIL,BESTELLWERT";
        $count = Db::name("cdkey_order")->count();
        p($count);
 
        $limit = 30000;
        $prevId = 0;
        for($i=1;$i<=ceil($count/$limit);$i++){
            echo ($i-1)*$limit.PHP_EOL;
            if($i==1){
                $data = Db::name("cdkey_order")->field($field)->limit(0,$limit)->select();
            }else{
                $data = Db::name("cdkey_order")->where("ID_CDKEY_ORDER",">",$prevId)->field($field)->limit(0,$limit)->select();
            }
 
            if(!$data){
                break;
            }
 
            $params['index'] = 'cdkey_order';//poetry这个document
            foreach($data as $k=>$v){
                $params['body'][]=array(
                    'index' => array(
                       //id我这里用的是数据库的自增id
                        '_id'=>$v['ID_CDKEY_ORDER']
                    ),
                );
 
                $params['body'][] = array(
                    'product_name'=>$v['PRODUCTS_NAME'],
                    'stamp'=>$v['STAMP'],
                    'email'=>$v['EMAIL'],
                    'amout'=>$v['BESTELLWERT'],
                );
            }
 
            $prevId = $v["ID_CDKEY_ORDER"];//获取最后一个customer_id
 
            $res = $client->bulk($params);
            unset($params);//用完这个变量要删除掉,不然这个标量会变得非常大
        }
}



问题1:

        ES集群的健康值是 red 状态. 删除之前 脏数据的索引。

[root@bogon www.es.com]# curl GET http://192.168.241.142:9200/_cluster/health?level=indices

{
	"cluster_name": "elasticsearch",
	"status": "red",
	"timed_out": false,
	"number_of_nodes": 1,
	"number_of_data_nodes": 1,
	"active_primary_shards": 0,
	"active_shards": 0,
	"relocating_shards": 0,
	"initializing_shards": 0,
	"unassigned_shards": 3,
	"delayed_unassigned_shards": 0,
	"number_of_pending_tasks": 0,
	"number_of_in_flight_fetch": 0,
	"task_max_waiting_in_queue_millis": 0,
	"active_shards_percent_as_number": 0.0,
	"indices": {
		"my_index": {
			"status": "red",
			"number_of_shards": 1,
			"number_of_replicas": 1,
			"active_primary_shards": 0,
			"active_shards": 0,
			"relocating_shards": 0,
			"initializing_shards": 0,
			"unassigned_shards": 2
		}
	}
}

        解决方法,删除这条索引数据(这条数据是楼主排查问题期间产生的脏数据,索引直接删除)

[root@bogon www.es.com]# curl -XDELETE 'http://192.168.241.141:9200/my_index'
{"acknowledged":true}

        刷新  es 健康状态。

        冷暖自知一抹茶ck


ES查询语法,请参考:Elasticsearch查询语法,只要将ES查询语法转换成PHP数组即可


        参考:

                PHP操作Elasticsearch

                实战!聊聊PHP如何使用 ElasticSearch 做搜索

                [精选] PHP操作ElasticSearch搜索引擎,一整个流程都在这了

        入门:

                Elasticsearch硬核入门教程(2022最全)

                为什么Elasticsearch7.x把type给干掉了?

                入门指南5.4


        

        问题:

                单机elasticsearch es 数据迁移健康状态一直是黄色问题解决

                ES健康状态red问题处理


冷暖自知一抹茶ck
请先登录后发表评论
  • 最新评论
  • 总共0条评论