2017-09-18 5 views
1

したがって、特定のIDとdataカラムを比較することによって、Laravelのnotificationsテーブルをクエリしたいとします。これはdata列がどのように見えるかです:LaravelのクエリビルダJSONセレクタ `field-> key`により構文エラーが発生する

{ 
    "Message": "some message", 
    "id": 3 
} 

、私はここ3に等しいIDを持つすべての通知を選択する必要があり、私はそれをやろうとした方法です。

DB::table('notifications')->where('data->id', '3')->get(); 

しかし、これは、次のエラーがスローされます。

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '>'$."id"' = ?' at line 1 (SQL: select * from notifications where data ->'$."id"' = 3)

私はここに私の心を失っていますが、誰も私を助けることができますか?

+1

LaravelはJSONをテキストとして保存するため、この方法ではクエリできません。 この情報をクエリするためにこの情報を保存する方法を変更する必要があります。そうしないと、 'data LIKE '%" id ":3%''のような全文検索が必要になりますが、 。 –

+0

これを見てください:https://stackoverflow.com/questions/44669673/laravel-eloquent-search-in-json-values-of-database –

答えて

4

あなたの質問に間違いありません。あなたの環境です。

LaravelのMySqlGrammarfield->'$.key'スタイルの抽出(MySQLの側)に(Laravel側)のフィールド名でfield->key表記を変換

問題:

/** 
* 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); 
} 

は、私はちょうどMariaDBがないことを確認しましたJSON_EXTRACT()関数のエイリアスとして-> extraction operatorをサポートします。ただし、同じクエリは、バニラのMySQL 5.7サーバーに対して機能します。このtestテーブルを想定し

╔════╤══════════════════╗ 
║ id │ payload   ║ 
╟────┼──────────────────╢ 
║ 1 │ {"a": 1, "b": 2} ║ 
╚════╧══════════════════╝ 

->抽出演算子を使用するクエリ:それは、MySQL 5.7.19に対する正しい2を得ながら

SELECT payload->"$.b" FROM test; 

はMariaDB 10.2.8に対して失敗サーバ。

ソリューション

適切な解決策は、プロダクションで使用しているものによって異なります。

MySQLを使用している場合はMariaDB

を交換し、あなたの開発ENVでのMySQLとMariaDBを交換してください。 homebrewで管理されているmacOSマシンでは、次のように簡単になります:

あなたのデータは元のままです。本番でMariaDBを使用している場合

が、しかし、あなたのクエリ

を書き換え

、あなたはElias already mentionedとしてJSON_EXTRACT()機能を使用するようにクエリを書き直す必要があります。ご覧のように、Laravel APIを使うともっと冗長にする必要があります。

上記のクエリは次のようになります。

SELECT JSON_EXTRACT(payload, "$.b") FROM test; 

1

問題がMySQLのは、クエリがMariaDBに失敗し、->演算子をサポートしていますが、ということです。

両方MariaDBMySQLのを解析JSON_EXTRACT機能をサポートしていますJSONと値を取得します。

あなたはこのようなクエリ実行して、それを解決することができます:Laravel's Query Builderでそれを行うには

SELECT * FROM notifications WHERE JSON_EXTRACT(`notifications.data`, "$.id") = 5 

を、あなたはDB::rawメソッドを使用する必要があります:

DB::table('notifications')->where(DB::raw('JSON_EXTRACT(`notifications.data`, "$.id")'), '=', 3); 

それを試してみて、私に教えてください間違っていたら。

注:JSON_EXTRACT()は@SepehrへMySQL >= 5.7またはMariaDB >= 10.2.3

おかげでのみ利用可能ですが、私は->は、MySQLオペレータませんでした、どちらもそのJSONタイプが存在することを知りませんでした。

+1

あなたの答えが問題の「周り」で働いていても、答えません質問。 LaravelがJSONを文字列として格納しているという記述は(https://github.com/laravel/framework/blob/5.3/src/Illuminate/Database/Schema/Blueprint.php#L695-L698)、JSONです型付きフィールドで、文字列型ではありません。それ以外に、Laravel 5.3以降では、JSON型のフィールドキー[' - >' notation](https://github.com/laravel/framework/blob/5.3/src/Illuminate/Database/Query/Grammarsを使って)をターゲットにすることができます/MySqlGrammar.php#L235-L246)を使用する代わりに、あなたが提案した生のクエリで 'JSON_EXTRACT'を使用します。 – sepehr

+0

あなたはまだ実際の問題に答えていません。 [JSON型](https://dev.mysql.com/doc/refman/5.7/en/json.html)と[' - >'演算子](https://dev.mysql)の両方。com/doc/refman/5.7/ja/json-search-functions.html#operator_json-column-path)が存在します。しかし、あなたはストレージの種類が正しいです。 LaravelのJSON型フィールドは、「longtext」型フィールドとして作成され、文字列です。しかし、構文エラーのない矢印表記を使用してそれらを依頼することはできます。これは[docs](https://laravel.com/docs/5.3/queries#json-where-clauses)にあります。 – sepehr

+0

実際の問題は、[' - >'抽出演算子](https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#operator_json-column-path)が[LaravelのMySQL文法で構築された](https://github.com/laravel/framework/blob/5.3/src/Illuminate/Database/Query/Grammars/MySqlGrammar.php#L235-L246)は、MariaDBに対して実行するとその構文エラーをスローします。 – sepehr

0

問題が->である:-)、私はあなたがそれでいくつかのコレクションと$データ呼ばVARを持っていると思います。

DB::table('notifications')->where($data->id, '3')->get(); 

それとも、テーブルその後、通知に関連したモデルがある場合:そのので、正しい方法がある場合は

Notification::where($data->id, '3')->get(); 

ModelNotification呼び出された場合

(雄弁大会に続きます)

すべてのIDが3の場合は、次のようになります。

DB::table('notifications')->where('id', '3')->get(); 
+0

OPの質問にある ' - >'表記は、[特別なL​​aravel表記法]です(https://github.com/laravel/framework/blob/5.3/src/Illuminate/Database/Query/Grammars/php#L254- L257)を使用してJSONフィールドのキーにアクセスします。最終的にMySQLの対応する[演算子](https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#operator_json-column-path)に変換されます。あなたの答えは、問題と全く無関係だと言っています。しかし、SOにようこそ。 – sepehr

+0

私はJSONについて理解しています。私は質問を間違って解釈したと思います –

2

私はJSONサポートのためLaravel MariaDBドライバーを作りました。ここをクリックしてください:ybr-nx/laravel-mariadb

+0

面白い!これはコアにあるべきです。 – sepehr

+0

それはすごくおいしいです、ありがとう! – Chilipepper

関連する問題