This is my current code, when executed will return no results. (Query1)
// Get all product categories that has a relation
$product_categories = ProductCategory::whereExists(function($query) {
$query->select('id')
->from('restaurants')
->whereJsonContains('restaurants.restaurant_categories', 'product_categories.name');
})->get();
// Log
dd($product_categories->toSql());
Here an sql query dump
select *
from `product_categories`
where exists (
select `id`
from `restaurants`
where json_contains(`restaurants`.`restaurant_categories`, ?)
)
and `product_categories`.`deleted_at` is null
While this when executed will return a result (Query2)
// Get all product categories that has a relation
$product_categories = ProductCategory::whereExists(function($query) {
$query->select('id')
->from('restaurants')
->whereJsonContains('restaurants.restaurant_categories', 'Food');
})->get();
// Log
dd($product_categories->toSql());
Here is an sql query dump as well
select *
from `product_categories`
where exists (
select `id`
from `restaurants`
where json_contains(`restaurants`.`restaurant_categories`, ?)
)
and `product_categories`.`deleted_at` is null"
Observation
- both sql dumps are the same
- difference between both queries is the second parameter of whereJsonContains
- in the first query i am passing the table column to the whereJsonContains method
- in the second query i am passing a row value directly
Question
- How do i get the query to filter using the row value on column name (getting Query1 to work).
- What did i miss?
For more context, These are what the tables looks like
table: restaurants
id | name | restaurant_categories |
---|---|---|
1 | fancy | ["Food"] |
table: product_categories
id | name | type |
---|---|---|
1 | Food | fragile |
This is my updated code, when executed will return no results. (Query3)
// Get all product categories that has a relation
$product_categories = ProductCategory::whereExists(function($query) {
$query->select('id')
->from('restaurants')
->whereJsonContains('restaurants.restaurant_categories', DB::raw('product_categories.name'));
})->get();
// Log
dd($product_categories->toSql());
Here is an sql query dump for Query3
select *
from `product_categories`
where exists (
select `id`
from `restaurants`
where json_contains(`restaurants`.`restaurant_categories`, product_categories.name)
)
and `product_categories`.`deleted_at` is null"
3
Answers
This works as expected. In both cases,
whereJsonContains()
is trying to match a string literal.Would give you a result if your
restaurants
table looked like this.If you want to try and match with the column instead of a string, try
You can use
JSON_SEARCH
instead:DB Fiddle
Eloquent should be like this:
the expected query:
laravel implementation: