【问题标题】:Laravel Elasticsearch JSON Mapping IssueLaravel Elasticsearch JSON 映射问题
【发布时间】:2020-10-17 03:03:49
【问题描述】:

我目前正在使用 Laravel v7.2,安装了 babenkoivan/scout-elasticsearch-driver (4.2),并且正在使用 AWS Elasticsearch 7.1。我在我的应用程序中映射了几个表,这些表工作正常,但是之前工作的嵌套映射出现问题,现在已损坏。

我正在将数据保存到表中,并将该表数据复制到 AWS Elasticsearch 中。我使用的是 MySQL 5.6,所以我使用 TEXT 列来存储 JSON 数据。表中数据如下:

'id' => 1,
'results' => [{"finish":1,"other_id":1,"other_data":1}]

我的模型设置具有以下映射:

protected $mapping = [
        'properties' => [
            'results' => [
                'type' => 'nested',
                'properties' => [
                    'finish' => [
                        'type' => 'integer'
                    ],
                    'other_id' => [
                        'type' => 'integer'
                    ],
                    'other_data' => [
                        'type' => 'integer'
                    ]
                ]
            ],
        ]
    ];

如果它有任何用处,toSearchableArray:

public function toSearchableArray()
    {
        $array = [
            'id' => $this->id,
            'results' => $this->results
        ];

        return $array;
    }

我创建这个索引没有问题,直到大约几个月前它才起作用。我不知道确切的时间,因为它不是一个高优先级项目,并且可能发生在 AWS ES 更新期间,但不确定为什么这会特别中断。我现在收到以下错误:

{"error":{"root_cause":[{"type":"mapper_parsing_exception","re​​ason":"[results] 的对象映射尝试将字段 [results] 解析为对象,但找到了具体值" }],"type":"mapper_parsing_exception","re​​ason":"[results] 的对象映射尝试将字段 [results] 解析为对象,但找到了具体值"},"status":400}

我也尝试将数据存储在表中,认为由于潜在的数组而导致数据中断,但无济于事:

'id' => 1,
'results' => {"finish":1,"other_id":1,"other_data":1}

我不知道还有什么办法可以让它再次工作。

编辑:这是整个模型:

<?php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use ScoutElastic\Searchable;


class ResultsModel extends Model
{

    use Searchable;

    protected $indexConfigurator = \App\MyIndexConfiguratorResults::class;

    protected $searchRules = [
        //
    ];

    protected $mapping = [
        'properties' => [
            'results' => [
                'type' => 'nested',
                'properties' => [
                    'finish' => [
                        'type' => 'integer'
                    ],
                    'other_id' => [
                        'type' => 'integer'
                    ],
                    'other_data' => [
                        'type' => 'integer'
                    ]
                ]
            ],
        ]
    ];

    public function searchableAs()
    {
        return 'results_index';
    }

    public function toSearchableArray()
    {
        $array = [
            'id' => $this->id,
            'results' => $this->results
        ];

        return $array;
    }
    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'results_table';

}

这里是\App\MyIndexConfiguratorResults::class

<?php

namespace App;

use ScoutElastic\IndexConfigurator;
use ScoutElastic\Migratable;

class MyIndexConfiguratorResults extends IndexConfigurator
{
    use Migratable;

    protected $name = "results_index";
    /**
     * @var array
     */
    protected $settings = [
        //
    ];
}

这就是每次更新表时让 Laravel 自动更新 AWS ES 所需的全部内容。对于初始加载,我将通过 SSH 登录并运行以下命令来创建索引。这以及elastic:migrate 和任何更新/插入表都会产生映射错误。

php artisan elastic:create-index results_index

【问题讨论】:

  • 你能分享你把$mapping作为属性的sn-p吗?你是怎么通过的?
  • @Joe 我已经编辑了答案以添加更多详细信息。希望这会有所帮助!
  • 确实是这样,但我需要看看你在哪里传递了 $mapping 变量。
  • 我实际上并没有在任何地方传递它。我相信是 Scout 在幕后处理这些问题。我相信 RisingSun 对不受支持的映射类型是正确的,但我目前正在测试以确认和确定未来的解决方案。

标签: laravel elasticsearch


【解决方案1】:

终于想通了,所以会为遇到此问题的任何人分享解决方案。结果证明是一个相当简单的修复,虽然我不确定它是如何工作的,所以这部分仍然令人困惑。

我创建了一个全新的索引并相应地更新映射以添加“id”并从“结果”部分中删除“嵌套”类型。 (添加“嵌套”类型是在索引中添加两个“结果”——一个包含我所有的嵌套数据,另一个只是“对象”。)

protected $mapping = [
        'properties' => [
            'id' => [
                'type' => 'integer'
            ],
            'results' => [
                'properties' => [
                    'finish' => [
                        'type' => 'integer'
                    ],
                    'other_id' => [
                        'type' => 'integer'
                    ],
                    'other_data' => [
                        'type' => 'integer'
                    ]
                ]
            ],
        ]
    ];

然后我简单地将json_decode 添加到toSearchableArray() 函数中:

public function toSearchableArray()
    {
        $array = [
            'id' => $this->id,
            'results' => json_decode($this->results, true)
        ];

        return $array;
    }

瞧。它成功地创建了索引并以我可以查询嵌套对象的方式导入数据。

【讨论】:

    【解决方案2】:

    阅读文档,type 字段似乎是removed。向下滚动到 7.x 以查看。此外,您似乎需要删除索引并重新添加它才能使新地图根据this page 工作。

    【讨论】:

    • 这是有道理的,但是当我检查我在 AWS 上的 composer.json 和我的 ES 的版本控制时,我实际上只是注意到自初始实施以来版本没有改变。所以,这是有效的,并且似乎在没有 ES 版本更新的情况下停止了。我尝试从我的映射中删除“类型”,但仍然遇到同样的问题。我也尝试删除“结果”的所有嵌套属性并加载,但只是将所有内容作为平面 json 存储在“结果”字段中,而不是将其分解。
    猜你喜欢
    • 1970-01-01
    • 2018-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多