YiluPHP
这家伙很懒,什么都没有留下...

经验 MeiliSearch在PHP中的使用示例

浏览数 10114 最后修改时间
官方安装文档:

对搜索结果排序的文档:

快速开始文档:

前提是你已经安装好MeiliSearch,并且已经启动,我给MeiliSearch设置了一个连接密码:yiluphp2017,连接时会用到。

一、先安装官网的PHP SDK

在快速开始文档中有安装SDK的方法


二、创建一个公共的PHP文件

里面实现引入SDK、实例化一个客户端对象。免得所有例子中都写一遍这些代码。
<?php

require_once __DIR__ . '/vendor/autoload.php';

use Meilisearch\Client;

$client = new Client('http://localhost:7700', 'yiluphp2017');


三、添加文档示例

<?php

require_once 'config.php';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // 当前请求是POST请求,执行相应逻辑
    $data = $_POST;
    if (trim($data['title']) == '' || trim($data['overview']) == '' || trim($data['genres']) == '') {
        echo '请填写完整';
        exit;
    }
    $data['poster'] = 'https://image.tmdb.org/t/p/w500/hAoluBzewlMqRH4mgFJvr4EPOMw.jpg';
    $data['release_date'] = time();

    //获取最大的id
    $search = $client->index('movies')->search(
        '',
        ['sort' => ['id:desc'],'limit' => 2],
        []
    );
    if (!$search = $search->getHits()) {
        $data['id'] = 1;
    }
    else {
        //获取数组中的第一个元素
        $search = array_shift($search);
        $data['id'] = $search['id'] + 1;
    }
    $client->index('movies')->addDocuments([$data]);
}

// 设置索引的可排序属性
//$client->index('movies')->updateSortableAttributes(['id']);

var_dump($search['id']);

?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加电影</title>
</head>
<body>
<form action="" method="post">
    <div>
        <label for="title">标题</label>
        <input type="text" name="title" id="title">
    </div>
    <div>
        <label for="overview">概述</label>
        <textarea type="text" name="overview" id="overview"></textarea>
        <label for="genres">流派</label>
        <input type="text" name="genres" id="genres">
    </div>
    <div>
        <input type="submit" value="提交">
    </div>
</form>
<hr>
<div>当前文档总数:<?php echo $client->index('movies')->stats()['numberOfDocuments']; ?></div>
<div>当前任务状态:</div>
<pre>
    <?php var_dump($client->getTask(0)); ?>
</pre>
</body>
</html>

四、批量导入json里的数据(这个是官方的例子)

<?php

require_once 'config.php';

$movies_json = file_get_contents('movies.json');
$movies = json_decode($movies_json);

$client->index('movies')->addDocuments($movies);

五、搜索文档示例

<?php
require_once 'config.php';

$data_list = [];
if ($keyword = trim($_GET['keyword'] ?? '')) {
    $search_params = [
        'attributesToHighlight' => ['title', 'overview'], // 高亮的字段
        'attributesToRetrieve'  => ['title', 'overview', 'genres', 'poster', 'release_date'], //检索的字段
        'cropLength'            => 50,               // 摘要长度
//    'cropMarker' => '<strong>',        // 高亮标记,使用<strong>可以在HTML中显示为加粗,它会包住所有的摘要内容
        'attributesToCrop'      => ['overview'], // 指定需要生成摘要的字段
        'limit'                 => 3,
        'offset'                => 3,
//    'sort' => ['release_date:desc'],  //AI自动帮我写的,暂未验收是否有用
//    'facetsDistribution' => ['genres'],  //AI自动帮我写的,暂未验收是否有用
        'highlightPreTag'       => '<span class="highlight">',  // 设置高亮的前缀标签
        'highlightPostTag'      => '</span>',  // 设置高亮的后缀标签
//    'facets' => ['genres'],  //AI自动帮我写的,暂未验收是否有用
    ];
    $data = $client->index('movies')->search($keyword, $search_params);
//    var_dump($data->count(), $data->getHitsCount(), $data->getHits());
    $data_list = $data->getHits();
}
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>搜索电影</title>
    <style>
        .highlight {
            color: red;
        }
        .item {
            margin: 10px 30px;
            padding: 1px 20px 20px 20px;
            background: #cccccc;
        }
    </style>
</head>
<body>
<form action="" method="get">
    <div>
        <label for="title">关键词</label>
        <input type="text" name="keyword" value="<?php echo $keyword; ?>">
    </div>
    <div>
        <input type="submit" value="搜索">
    </div>
</form>
<hr>

<?php if (!$data_list): ?>
    <div>请输入关键词进行搜索</div>
<?php endif; ?>

<div>
    搜索命中总数:<?php echo $data->getEstimatedTotalHits(); ?>,
    从第<?php echo $data->getOffset(); ?>条开始返回,
    当前是第<?php echo floor($data->getOffset()/$data->getLimit()) + 1; ?>页,
    每页数量:<?php echo $data->getLimit(); ?>,
    当前页返回数量:<?php echo $data->getHitsCount(); ?>
</div>
<?php foreach ($data_list as $item): ?>
    <div class="item">
        <h3>
            <?php echo $item['_formatted']['title']; ?>
        </h3>
        <div>
            <?php echo $item['_formatted']['overview']; ?>
        </div>
    </div>
<?php endforeach; ?>

<div>返回的数据结构:</div>
<pre>
    <?php !$data ? '' : var_dump($data); ?>
</pre>
</body>
</html>

六、给字段设置排序权重

例如:如果一个内容匹配到aa字段,另一个内容bb字段,我需要将匹配到bb字段的内容排在前面
在 MeiliSearch 中,你可以通过设置字段权重来调整不同字段对搜索结果排序的影响。这个功能称为 ranking rules 或 custom ranking。如果你想让匹配到 bb 字段的内容比匹配到 aa 字段的内容排名更高,你可以通过修改索引的排序规则来实现这一点。

步骤一:获取当前的排序规则

首先,你可能想要查看当前索引的排序规则,这可以帮助你了解默认的排序配置:
$rankingRules = $client->index('pages_cn')->getRankingRules();
print_r($rankingRules);
输出:
Array
(
    [0] => words
    [1] => typo
    [2] => proximity
    [3] => attribute
    [4] => sort
    [5] => exactness
)

步骤二:修改排序规则

你可以添加一个自定义的排序规则,使得 bb 字段的匹配权重更高。这通常涉及到在排名规则中增加字段的权重:
$rankingRules = [
        'words',
        'typo',
        'proximity',
        'attribute',
        'title_cn:asc', //给中文标题权重加权
        'content_cn:asc', //给中文内容权重加权
        'sort',
        'exactness',
    ];
    $client->index('pages_cn')->updateRankingRules($rankingRules);
在这个例子中,title_cn:asc 表示当搜索查询匹配到 title_cn 字段时,这些结果将会被提升。asc 或 desc 表示升序或降序排列,这取决于你的具体需求。请注意,更新排名规则可能需要一些时间来重新索引数据。

步骤三:确认更新

更新排序规则后,你可能想要确认这些更改已被正确应用:
$updatedRules = $client->index('pages_cn')->getRankingRules();
print_r($updatedRules);
输出:
Array
(
    [0] => words
    [1] => typo
    [2] => proximity
    [3] => attribute
    [4] => title_cn:asc
    [5] => content_cn:asc
    [6] => sort
    [7] => exactness
)

注意事项
  • 性能影响:频繁地修改排序规则和重新索引可能会对性能产生一定影响,特别是在处理大量数据时。
  • 测试:更改排序规则后,建议进行适当的测试以确保它们按预期工作,并且实际上改善了搜索结果的相关性和排序。
通过这种方式,你可以精确地控制搜索结果的排序,优先展示对用户更为相关的内容。如果有任何其他问题或需要进一步的帮助,请随时询问!

七、设置MeiliSearch为开机启动

步骤一:创建 Systemd 服务文件

1、打开文本编辑器,创建一个名为 meilisearch.service 的新文件:
sudo nano /etc/systemd/system/meilisearch.service

2、添加以下内容到文件中,适当修改 <path-to-meilisearch> 和 <your-master-key> 来匹配你的 MeiliSearch 二进制文件路径和设置的密码(如果使用):
[Unit]
Description=MeiliSearch
After=network.target

[Service]
Type=simple
ExecStart=<path-to-meilisearch>/meilisearch --http-addr '127.0.0.1:7700' --master-key '<your-master-key>'
Restart=always

[Install]
WantedBy=multi-user.target
如:
[Unit]
Description=MeiliSearch
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/meilisearch/meilisearch --http-addr '0.0.0.0:7700' --master-key='yiluphp2017'
Restart=always

[Install]
WantedBy=multi-user.target

  • Description: 服务的描述。
  • After: 确保网络服务在 MeiliSearch 启动前已经启动。
  • Type: 设置为 simple 表示 systemd 在 ExecStart 指定的程序作为主服务程序后台运行。
  • ExecStart: 启动命令,确保正确设置了路径和任何必要的选项。
  • Restart: 设置为 always 以确保在程序退出时 systemd 自动重启服务。
  • WantedBy: 设置此服务由哪个目标拉起。
3、保存并退出编辑器(在 Nano 中,使用 Ctrl+O 保存,然后使用 Ctrl+X 退出)。

步骤二:启用和启动服务

1、重新加载 systemd 以确保它识别新的服务文件:
sudo systemctl daemon-reload

2、启动 MeiliSearch 服务:
sudo systemctl start meilisearch

3、设置 MeiliSearch 服务为开机自启:
sudo systemctl enable meilisearch

4、检查服务状态,确认没有错误:
sudo systemctl status meilisearch

通过这些步骤,MeiliSearch 将被设置为每次机器启动时自动启动,使用你指定的配置运行。你还可以通过 systemctl 命令管理 MeiliSearch 服务(如停止、重新启动等)。这样,你可以确保 MeiliSearch 作为后台服务稳定运行。



我来说说