使用ThinkPHP (TP) 5.0 和 Elasticsearch (ES) 实现文章搜索功能是一种常见的需求,尤其是在需要高效全文搜索的场景下。

使用场景

  • 全文搜索:用户可以通过关键词搜索到包含这些关键词的文章。
  • 智能排序:根据相关性、发布时间等因素对搜索结果进行排序。
  • 高级过滤:支持按照类别、作者等条件进行过滤搜索。

底层原理

Elasticsearch 是一个分布式的搜索和分析引擎,它使用倒排索引技术来快速检索文档。当文档被索引时,ES 会将文档中的每一个词作为键,文档ID作为值存入索引中。这样,当你查询某个词时,ES 可以迅速找到包含这个词的所有文档。

实现步骤

1. 准备环境

确保你的开发环境中已经安装了 PHP、Composer、MySQL 数据库以及 Elasticsearch。

2. 创建 TP5.0 项目

通过 Composer 创建一个新的 TP5.0 项目。

composer create-project topthink/think tp5.0
cd tp5.0
3. 安装 Elasticsearch 客户端

安装官方提供的 PHP 客户端来与 ES 交互。

composer require elasticsearch/elasticsearch
4. 创建文章模型和控制器

创建一个用于存储文章信息的数据模型,并设置对应的控制器来处理文章的 CRUD 操作。

5. 文章索引化

每次新增或修改文章时,都需要更新 ES 中的文章索引。

// 假设这是你的模型类中的方法
public function indexDocument($article)
{
    $client = \Elasticsearch\ClientBuilder::create()->build();
    $params = [
        'index' => 'articles',
        'type' => '_doc',
        'id' => $article['id'],
        'body' => $article
    ];
    $client->index($params);
}

// 在保存文章时调用此方法
public function saveArticle($articleData)
{
    $article = new ArticleModel();
    $article->save($articleData);
    $this->indexDocument($articleData);
}
6. 实现搜索功能

创建一个用于搜索文章的方法,该方法会从 ES 中查询数据,并返回给前端。

public function searchArticles($query)
{
    $client = \Elasticsearch\ClientBuilder::create()->build();
    $params = [
        'index' => 'articles',
        'body' => [
            'query' => [
                'match' => [
                    'content' => $query
                ]
            ]
        ]
    ];

    $results = $client->search($params);
    return $results['hits']['hits'];
}
7. 前端展示

在前端页面中添加搜索框,并使用 AJAX 技术来异步请求搜索结果,然后在页面上显示出来。

<form id="search-form">
    <input type="text" name="query" placeholder="Search articles...">
    <button type="submit">Search</button>
</form>

<div id="search-results"></div>

<script>
document.getElementById('search-form').addEventListener('submit', function(event) {
    event.preventDefault();
    const query = this.querySelector('input[name=query]').value;
    fetch('/api/search?q=' + encodeURIComponent(query))
        .then(response => response.json())
        .then(data => {
            const resultsDiv = document.getElementById('search-results');
            resultsDiv.innerHTML = ''; // 清空结果
            data.forEach(article => {
                const div = document.createElement('div');
                div.innerHTML = `<h2>${article._source.title}</h2><p>${article._source.content}</p>`;
                resultsDiv.appendChild(div);
            });
        });
});
</script>

以上步骤给出了一个基本的实现框架,具体细节如错误处理、分页、安全验证等可能需要进一步完善。

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐