I'm trying to migrate a Laravel app with spatie/laravel-translatable 6.3 from MySQL 8 into Postgres 14: in a table defined
Schema::create('quiz_categories', function (Blueprint $table) {
$table->id();
$table->json('name')->comment('This column is used for i18n support');
$table->boolean('active')->default(false);
and in app/Models/QuizCategory.php:
class QuizCategory extends Model
{
use HasTranslations;
protected $table = 'quiz_categories';
public $translatable = ['name'];
protected $primaryKey = 'id';
public $timestamps = false;
protected $casts = [
'active' => 'boolean',
'name' => 'json'
];
protected $fillable = ['name', 'active'];
public function scopeGetByActive($query, $active = null)
{
if (! isset($active)) {
return $query;
}
return $query->where($this->table . '.active', (bool)$active);
}
But with request
$quizCategories = QuizCategory::orderBy('name', 'desc')
->getByActive($filterActive)->get();
I got error:
SQLSTATE[42883]: Undefined function: 7 ERROR: could not identify an ordering operator for type json LINE 1: ...s" where "quiz_categories"."active" = $1 order by "name" des... ^ HINT: Use an explicit ordering operator or modify the query.
SELECT * FROM "quiz_categories" WHERE "quiz_categories"."active" = 1 ORDER BY "name" DESC
Testing the SQL query in PhpgMyAdmin looks like I need :
a) to remake request to be rendered as
"quiz_categories"."active" = true
Not sure how can I do it in eloquent?
b) I need to remove
ORDER BY "name" DESC
Can I make ordering by JSON field somehow?
MySQL executed my code, but I am not sure that it worked correctly
UPDATED_INFO : I returned to this issue and looks like I skipped something last time, as with code:
$quizCategories = QuizCategory::query()
->getByActive()
->orderByRaw('name->"$.en"', 'desc')
->get();
I got error :
SQLSTATE[42703]: Undefined column: 7 ERROR: column "$.en" does not exist LINE 1: select * from "quiz_categories" order by name->"$.en" ^
SELECT * FROM "quiz_categories" ORDER BY name->"$.en"
What is wrong ? Please give a reference to docs where such code is used...
UPDATED_INFO # 2 : With request :
$quizCategories = QuizCategory::query()
->getByActive()
->orderBy(DB::raw("json_extract('name', '$.en')"), 'desc')
->get();
I got error :
function json_extract(unknown, unknown) does not exist
Searching in next I found method json_extract_path, but with code :
$quizCategories = QuizCategory::query()
->getByActive()
->orderBy(DB::raw("json_extract_path('name', '$.en')"), 'desc')
->get();
I got different error :
SQLSTATE[22P02]: Invalid text representation: 7 ERROR: invalid input syntax for type json LINE 1: ...from "quiz_categories" order by json_extract_path('name', '$... ^ DETAIL: Token "name" is invalid. CONTEXT: JSON data, line 1: name
?
UPDATED_INFO # 3 : I use postgresql-14. I check https://www.postgresql.org/docs/14/functions-json.html
Looks like it has json_extract_path function (but I got error with it I mentioned above)
I found text :
jsonb -> text → jsonb
Extracts JSON object field with the given key.
'{"a": {"b":"foo"}}'::json -> 'a' → {"b":"foo"}
it looks like code with
'name->"$.en"'
But I have an error with it...
UPDATED_INFO # 4 :
With
$quizCategories = QuizCategory::query()
->getByActive()
->orderBy(DB::raw("name->>en"), 'desc')
->get();
I got error :
Undefined column: 7 ERROR: column "en" does not exist LINE 1: select * from "quiz_categories" order by name->>en desc ^