问题
I'm trying to use the jsonb exists operator '?' in Laravel's query builder, and have it use an index, but I've run into some issues.
Sample query
DB::table('table_name')->whereRaw("jsonb_column ? 'key'")->get();
Sample Index
CREATE INDEX ON table_name USING GIN(jsonb_column jsonb_ops)
The main issue seems to be that '?' is reserved for parameter replacement, so this query returns a syntax error. I've found a couple ways around this, but each are incomplete solutions.
use '??' (a way to escape the ?)
->whereRaw("jsonb_column ?? 'key'")
- doesn't work with querybuilder. returns
SQLSTATE[42883]: Undefined function: 7 ERROR: operator does not exist: jsonb ?? unknown
- works with raw queries, e.g.
DB::select("SELECT * FROM table_name WHERE jsonb_column ?? 'key'")
, but I need it to work with the query builder.
- doesn't work with querybuilder. returns
use a named function / create an alias for the operator
- '?' translates to the function - jsonb_exists(jsonb, text)
->whereRaw("jsonb_exists(jsonb_column, 'key')")
CREATE OPERATOR @-> ( PROCEDURE = jsonb_exists, LEFTARG = jsonb, RIGHTARG = text );
->whereRaw("jsonb_column @-> 'key'")
- these solutions both "work"... but they don't use indexes
- '?' translates to the function - jsonb_exists(jsonb, text)
Right now I'm researching CREATE OPERATOR CLASS
, as a way to get my custom operator to use gin indexing, but it's a bit over my head. If anybody can give me some tips on how to accomplish this or, even better, some simpler solution, it'd be a huge help.
edit
- using php 7.3
回答1:
PHP 7.4 allows you to escape the placeholder with ??
: https://wiki.php.net/rfc/pdo_escape_placeholders
DB::table('table_name')->whereRaw('jsonb_column ?? ?', ['key'])->get();
来源:https://stackoverflow.com/questions/60310077/how-to-use-postgres-jsonb-operator-in-laravel-with-index-support