Nie ma nic złego w Twoim zapytaniu. To Twoje środowisko.
Problem
MySqlGrammar
tłumaczy pole->klucz
notacja w nazwach pól (po stronie Laravela) w field->'$.key'
Ekstrakcje w stylu (po stronie MySQL):
/**
* Wrap the given JSON selector.
*
* @param string $value
* @return string
*/
protected function wrapJsonSelector($value)
{
$path = explode('->', $value);
$field = $this->wrapValue(array_shift($path));
$path = collect($path)->map(function ($part) {
return '"'.$part.'"';
})->implode('.');
// Here:
return sprintf('%s->\'$.%s\'', $field, $path);
}
Właśnie potwierdziłem, że MariaDB nie obsługuje -> operator ekstrakcji
jako alias do JSON_EXTRACT()
funkcjonować. Jednak to samo zapytanie działa na waniliowym serwerze MySQL 5.7.
Zakładając ten test
tabela:
╔════╤══════════════════╗
║ id │ payload ║
╟────┼──────────────────╢
║ 1 │ {"a": 1, "b": 2} ║
╚════╧══════════════════╝
Zapytanie używające ->
operator ekstrakcji:
SELECT payload->"$.b" FROM test;
nie działa przeciwko MariaDB 10.2.8, podczas gdy zwraca poprawne 2
przeciwko serwerowi MySQL 5.7.19.
Rozwiązania
Właściwe rozwiązanie zależy od tego, czego używasz na produkcji.
Zastąp MariaDB
Jeśli używasz MySQL, zamień MariaDB na MySQL w swoim środowisku deweloperskim. Na komputerze z systemem macOS zarządzanym przez homebrew byłoby to tak proste, jak:
brew services stop mysql
brew uninstall mariadb
brew install mysql
brew services start mysql
Twoje dane pozostaną nienaruszone.
Przepisz swoje zapytania
Jeśli jednak używasz MariaDB w środowisku produkcyjnym, musisz przepisać swoje zapytania tak, aby używały metody JSON_EXTRACT()
działa jako Wspomniany już Elias
. Jak widzisz, musisz być bardziej gadatliwy z API Laravel.
Powyższe zapytanie brzmiałoby:
SELECT JSON_EXTRACT(payload, "$.b") FROM test;