ohffs's avatar
Level 50

JSON column - find any matching value

I have a db with a json column that's used to store a whole lot of nested data. I was wondering if anyone knows if (ideally via Eloquent) you can do something like :

Model::where('mycolumn->*', 'like', '%searchterm%')->get();

I've had a look at the mysql json column docs and nothing was leaping out at me :-/

0 likes
8 replies
Dchubb's avatar

You wont be able to do that with the query builder since it translates to SQL.

Instead you can do your filtering through PHP.

Model::all()->filter(function($model) {

            return strpos(json_decode($model->mycolumn)->myattribute, 'searchterm') !== false;
        });
ohffs's avatar
Level 50

@staudenmeir it's an object - which in turn contains lots of other nested objects. It's pretty much a dump of $request->all() for some complicated forms with 100's of fields.

ohffs's avatar
Level 50

@Dchubb ah - I was hoping the new json syntax in mysql would let me do it natively :-/ Fetching all the records and filtering them would be a bit 'costly' as there are many, many thousands of them :-/

My hacky way around it would be to store the data as one big concatenated text column and do a like query against that - but I'd much rather avoid that if I can...

36864's avatar
36864
Best Answer
Level 13

You could use a raw query:

Model::whereRaw('json_field->"$[*].*" like ?', "%$searchterm%")->get()
ohffs's avatar
Level 50

@36864 @bestmomo ah - fair enough I guess. Thanks for the pointer - I can avoid my hacky text column now and feel a little less guilty when I look at the code :-) Thanks again :-)

ohffs's avatar
Level 50

For anyone else who needs to do this, this is what I've got working on the model (assuming your json column is called 'data') :

public static function searchFor(string $term)
{
    return static::whereRaw("JSON_SEARCH(data, 'all', ?) IS NOT NULL", ["%{$term}%"])->get();

}

Then elsewhere you can do :

$results = Model::searchFor('hello');
1 like

Please or to participate in this conversation.