You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Scout集成AWS OpenSearch搜索时触发illegal_argument_exception

Laravel Scout + OpenSearch 搜索报错解决方案

问题背景

在Laravel 10项目中使用zingimmick/laravel-scout-opensearch驱动,由于数据表无自增ID,无法通过php artisan scout:import命令同步数据,因此手动执行以下代码同步了50条Asset模型数据:

Asset::query()
    ->limit(50)
    ->get()
    ->searchable();

Asset模型代码如下:

class Asset extends Model
{
    use Searchable;

    public $timestamps = false;

    protected $fillable = [
        'policy_id',
        'asset_id',
        'fingerprint',
        'asset_name',
    ];

    public function searchableAs(): string
    {
        return 'assets_index';
    }

    public function getScoutKey(): string
    {
        return $this->policy_id . $this->asset_id;
    }
}

数据已成功同步到OpenSearch的assets_index索引中,但执行搜索代码时触发错误:

Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [id] in order to load field data by uninverting the inverted index. Note that this can use significant memory.

问题根源

Laravel Scout默认会将getScoutKey()返回的值同时作为OpenSearch文档的_id和文档中的id字段存储,但该id字段在索引中被自动映射为text类型。而Scout在获取搜索结果时,需要对id字段进行排序或聚合操作,text类型默认不支持这类操作,因此抛出上述错误。

解决步骤

方案一:自定义Scout主键字段名(推荐)

在Asset模型中新增getScoutKeyName()方法,指定自定义的主键字段名,避免使用默认的id字段:

class Asset extends Model
{
    use Searchable;

    public $timestamps = false;

    protected $fillable = [
        'policy_id',
        'asset_id',
        'fingerprint',
        'asset_name',
    ];

    public function searchableAs(): string
    {
        return 'assets_index';
    }

    public function getScoutKey(): string
    {
        return $this->policy_id . $this->asset_id;
    }

    // 指定自定义主键字段名
    public function getScoutKeyName(): string
    {
        return 'asset_key';
    }
}

之后需要:

  1. 通过OpenSearch控制台或API删除已有的assets_index索引
  2. 重新执行数据同步代码:
    Asset::query()
        ->limit(50)
        ->get()
        ->searchable();
    

此时,OpenSearch文档的_id仍会使用getScoutKey()的值,而文档内的主键字段会是asset_key(自动映射为keyword类型),Scout处理结果时不会再触发text字段的操作限制。

方案二:修改现有索引的id字段映射(不推荐)

如果不想重新创建索引,可以通过OpenSearch API修改id字段的映射,将其改为keyword类型:

PUT /assets_index/_mapping
{
  "properties": {
    "id": {
      "type": "keyword"
    }
  }
}

或者开启fielddata=true(会占用大量内存,不推荐):

PUT /assets_index/_mapping
{
  "properties": {
    "id": {
      "type": "text",
      "fielddata": true
    }
  }
}

内容的提问来源于stack exchange,提问作者Latheesan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 01:17:33