博客

从 ES|QL 到 PHP 对象

学习如何在 PHP 中执行和管理 ES|QL 查询。请按照本指南将 ES|QL 结果映射到 PHP 对象或自定义类。

从 elasticsearch-phpv8.13.0开始,您可以执行ES|QL查询,并将结果映射到stdClass或自定义类的 PHP 对象。

ES|QL

ES|QL是 Elasticsearch 8.11.0 中引入的一种新的 Elasticsearch 查询语言。目前,它还处于技术预览阶段。它为过滤、转换和分析存储在 Elasticsearch 中的数据提供了一种强大的方法。

它利用"管道" (|) 来逐步操作和转换数据。通过这种方法,用户可以进行一系列操作,其中一个操作的输出将成为下一个操作的输入,从而实现复杂的数据转换和分析。

例如,下面的查询返回sample_data 索引的前 3 个文档(行):

FROM sample_data
| LIMIT 3
ES|QL 生成表格

使用案例:官方 PHP 客户端中的 ES|QL 功能

为了说明在官方 PHP 客户端中开发的 ES|QL 功能,我们在 Elasticsearch 中存储了一个包含 81,828 本图书(54.4 MB)的CSV 文件,其中包括以下信息:

Title;Descrition;Author;Year;Publisher;Ratings

我们从公开的亚马逊图书评论数据集中提取了这份清单。

我们使用以下 Elasticsearch 映射创建了books 索引:

'mappings' : {
    'properties': {
        'title': {
            'type': 'text'
        },
        'description': {
            'type': 'text'
        },
        'author': {
            'type': 'text'
        },
        'year': {
            'type': 'short'
        },
        'publisher': {
            'type': 'keyword'
        },
        'rating': {
            'type': 'half_float'
        }
    }
}

rating 值是从 2.9 GB 的Books_rating.csv文件中提取的评论排名平均值。

在这里,你可以找到我们用来批量导入 Elasticsearch 中所有图书的 PHP 脚本。使用 PHP 8.2.17 进行批量操作耗时 7 秒,占用 28 MB 内存。使用建议的映射后,Elasticsearch 中的索引大小约为 62 MB。

将 ES|QL 结果映射到 PHP 对象或自定义类

我们可以使用esql()->query() 端点在 PHP 中执行 ES|QL 查询。查询结果是一个表格数据结构。这在 JSON 中使用columnsvalues 字段来表示。在columns 字段中,我们有nametype 的定义。

下面是一个 ES|QL 查询示例,用于检索斯蒂芬-金著作中按用户评论排名排序的前 10 本书籍:

$query = <<<EOD
    FROM books
    | WHERE author == "Stephen King"
    | SORT rating DESC
    | LIMIT 10
EOD;

$result = $client->esql()->query([
    'body' => ['query' => $query]
]);

来自 Elasticsearch 的 JSON 结果如下:

{
    "columns": [
        { "name": "author", "type": "text" },
        { "name": "description", "type": "text" },
        { "name": "publisher", "type": "keyword" },
        { "name": "rating", "type": "double" },
        { "name": "title", "type": "text" },
        { "name": "year", "type": "integer" }
    ],
    "values": [
        [
            "Stephen King",
            "The author ...",
            "Turtleback",
            5.0,
            "How writers write",
            2002
        ],
        [
            "Stephen King",
            "In Blockade Billy, a retired coach...",
            "Simon and Schuster",
            5.0,
            "Blockade",
            2010
        ],
        [
            "Stephen King",
            "A chilling collection of twenty horror stories.",
            "Signet Book",
            4.55859375,
            "Night Shift (Signet)",
            1979
        ],
        ...
    ]
}

在这个例子中,我们有 6 个与一本书相关的属性(作者、描述、出版商、评分、标题、年份)和 10 个结果,都是斯蒂芬-金的书。

这里列出了 ES|QL 支持的所有类型。

$result 响应对象可以数组、字符串或对象的形式访问(更多信息,请参见此处)。

使用对象接口,我们可以使用属性和索引访问值。例如,$result->values[0][4] 返回列表中第一本书(0)的书名(4),$result->values[1][3] 返回第二本书(1)的等级分(3),等等。请记住,PHP 中数组的索引是从 0 开始的。

对于某些使用情况,这个接口已经足够好了,但大多数情况下,我们希望得到一个对象数组的结果。

要将结果映射到对象数组中,我们可以使用 elasticsearch-php 的新功能mapTo()。

该功能可直接在Elasticsearch 响应对象中使用。这意味着您可以通过以下方式访问它:

$books = $result->mapTo(); // Array of stdClass
foreach ($books as $book) {
    printf(
        "%s, %s, %d, Rating: %.2f\n",
        $book->author,
        $book->title,
        $book->year,
        $book->rating
    );
}

如果您有一个自定义的图书类,可以使用它来映射结果,如下所示:

class Book
{
    public string $author;
    public string $title;
    public string $description;
    public int $year;
    public float $rating;
}

$books = $result->mapTo(Book::class); // Array of Book

如果您的类除了 ES|QL 结果中包含的属性外还有其他属性,这也同样有效。mapTo() 函数将只使用作为 ES|QL 结果列返回的属性。

您可以在此下载本文中报告的所有示例。

常见问题

什么是 ES|QL?

ES|QL 是 Elasticsearch 8.11.0 中引入的 Elasticsearch 查询语言。它为过滤、转换和分析存储在 Elasticsearch 中的数据提供了一种强大的方法。

相关内容

LINQ to Elasticsearch ES|QL:编写 C# 代码,查询 Elasticsearch

Florian Bernd

使用 ES|QL 进行 Elasticsearch 地理空间搜索

Craig Taverner

基于 Swiss 式哈希表实现更快的 ES|QL 统计数据

Chris Hegarty

在 Google MCP Toolbox for Databases 中引入 Elasticsearch 支持

Enrico Zimuel

使用 Kibana 将地理空间数据输入 Elasticsearch,以便在 ES|QL 中使用

Craig Taverner

准备好打造最先进的搜索体验了吗?

足够先进的搜索不是一个人的努力就能实现的。Elasticsearch 由数据科学家、ML 操作员、工程师以及更多和您一样对搜索充满热情的人提供支持。让我们联系起来,共同打造神奇的搜索体验,让您获得想要的结果。

亲自试用