一、项目背景:
我们要做一个项目,此项目包含字、词、成语、诗句,可供给用户查询.
我们分析出来一批用的常规需求。
比如用户搜索 “好”怎么读
与“乐同音”的字、同笔画得字.
写“荷花”的诗有哪些?
这些分析无非就是要根据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
    }
 ]

用以上代码足够创建一个简单的小型搜索项目了,多数数据都从上面演化而来,有更复杂的查询和原理,咱们后面再聊.~~