Elasticsearch 中文搜索以及 PHP 客户端的使用

准备工作

安装

Elasticsearch 很容易安装,解压到指定目录即可。然后解压分词插件,切换到插件根目录,使用命令行编译打包:

mvn package

打包后的文件名类似 target/releases/elasticsearch-analysis-ik-xxx.zip,将其解压到 Elasticsearch目录/plugins/ik, 然后使用 Elasticsearch目录/bin 里的脚本启动 Elasticsearch.

安装 PHP 客户端

使用 Composer 安装客户端:

composer require elasticsearch/elasticsearch

创建索引并设置 Mappings

创建一个名为 init.php 文件,内容如下:

<?php
use Elasticsearch\ClientBuilder;
require 'vendor/autoload.php';
$client = ClientBuilder::create()->build();

// 创建一个名为 `demo` 的索引:
$params= ['index' => 'demo'];
$client->indices()->create($params);

// 设置 mappings
$params = [
    'index' => 'demo',
    'type' => 'demotype',
    'body' => [
        'demotype' => [
            '_all' => [
                "analyzer"=> "ik_max_word",
                "search_analyzer" => "ik_max_word",
                "term_vector" => "no",
                "store" => false
            ],
            'properties' => [
                'content' => [
                    'type' => 'string',
                    'store' => 'no',
                    'term_vector' => 'with_positions_offsets',
                    'analyzer' => 'ik_max_word',
                    'search_analyzer' => 'ik_max_word',
                    'include_in_all' => true,
                    'boost' => 8,
                ],
            ]
        ]
    ]
];

print_r($client->indices()->putMapping($params));

运行 init.php,初始化 demo 索引,并设置 Mappings 。Mappings 也可以在创建索引的时候一起设置。

索引数据

创建一个名为 add.php,内容如下:

<?php
use Elasticsearch\ClientBuilder;
require 'vendor/autoload.php';
$client = ClientBuilder::create()->build();

// 添加测试索引数据,用 index 方法

foreach([
    '美国留给伊拉克的是个烂摊子吗',
    '公安部:各地校车将享最高路权',
    '中韩渔警冲突调查:韩警平均每天扣1艘中国渔船',
    '中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首',
] as $content) {
    $client->index([
        'index' => 'demo',
        'type' => 'demotype',
        'body' => [
            'content' => $content,
        ]
    ]);
}

搜索数据

创建一个名为 search.php 的文件,内容如下:

<?php
use Elasticsearch\ClientBuilder;
require 'vendor/autoload.php';
$client = ClientBuilder::create()->build();

$params = [
    'index' => 'demo',
    'type' => 'demotype',
    'body' => [
        "query" => [
            "term" => ["content" => "中国"]
        ],
    ]
];

print_r($client->search($params));

批量处理

客户端可以一次将多个操作合并为一个请求,以提高性能。比如以上的索引操作。

<?php

$body = [];
foreach([
    '美国留给伊拉克的是个烂摊子吗',
    '公安部:各地校车将享最高路权',
    '中韩渔警冲突调查:韩警平均每天扣1艘中国渔船',
    '中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首',
] as $content) {
    $body[] = '{"index":{}}' // 索引操作
        . "\n"
        . json_encode([
            'content' => $content,
        ]);
}

$client->bulk([
    'index' => 'demo',
    'type' => 'demotype',
    'body' => implode("\n", $body),
]);

使用别名

<?php

$params = [
    'index' => 'demo',
    'name' => 'demoalias'
];

if (! $client->indices()->existsAlias($params)) {
    $client->indices()->putAlias($params);
}

索引重建

reindex 操作会将原索引另存为新索引。

<?php

$client->reIndex([
    "body" => [
        "source" => [
            "index" => "demo",
        ],
        "dest" => [
            "index" => "newdemo",
        ]
    ]
]);

PHP 客户端注意事项

由于 PHP 不像 javascript 那样,不能用 {} 表示空对象,可以用 new \stdClass()(object)[] 代替。