Find price greater than using JSON operators - json

Json:
"availability": [
{
"qty": 25,
"price": 3599,
"is_available": true
},
{
"qty": 72,
"price": 3599,
},
"is_available": true
]
If I want to find price with value = "3599" I use this query:
select *
from product
where to_tsvector(product.data #>> '{availability}') ## to_tsquery('3599')
or this query:
SELECT *
FROM product
WHERE product.data #> '{"availability": [ { "price": 3599} ] }';
Nice. It's work fine.
But I need also to find price > 1000
I try this:
select *
from product
where to_tsvector(product.data #>> '{availability}') ## to_tsquery('>1000')
But the result is empty (nothing found).

Full text search is the wrong tool for this kind of queries.
With Postgres 12, you can use a JSON/Path expression:
select *
from product
where data ## '$.availability[*].price > 100';
For older Postgres versions you need to unnest the array:
select *
from product
where exists (select *
from jsonb_array_elements(data -> 'availability') as x(item)
where (x.item ->> 'price')::int > 100);

Related

JSON EXTRACT SUM returning 0 instead of correct value

I'm trying to sum the contents of a json array in a mysql database, below is the JSON format and the query I'm running. Is there something wrong with it?
// Options JSON Format:
[
{
"optionId": 1,
"optionName": "With Meat",
"optionPrice": 2000
},
{
"optionId": 2,
"optionName": "With Veggies",
"optionPrice": 0
}
]
// Query:
SELECT id, SUM(options->'$[*].optionPrice') FROM table_order_items GROUP BY id;
The result is 0, when it should be 2000
While this query:
SELECT id, options->'$[*].optionPrice' FROM table_order_items;
correctly returns [2000,0]
You need the function JSON_TABLE() to extract the prices:
SELECT t.id,
SUM(j.price) AS total
FROM table_order_items t
JOIN JSON_TABLE(
t.options,
'$[*]' COLUMNS(price INT PATH '$.optionPrice')
) j
GROUP BY t.id;
See the demo.

How to deal with not existing values using JSON_EXTRACT?

I have a list ob objects. Each object contains several properties. Now I want to make a SELECT statement that gives me a list of a single property values. The simplified list look like this:
[
[
{
"day": "2021-10-01",
"entries": [
{
"name": "Start of competition",
"startTimeDelta": "08:30:00"
}
]
},
{
"day": "2021-10-02",
"entries": [
{
"name": "Start of competition",
"startTimeDelta": "03:30:00"
}
]
},
{
"day": "2021-10-03",
"entries": [
{
"name": "Start of competition"
}
]
}
]
]
The working SELECT is now
SELECT
JSON_EXTRACT(column, '$.days[*].entries[0].startTimeDelta') AS list
FROM table
The returned result is
[
"08:30:00",
"03:30:00"
]
But what I want to get (and also have expected) is
[
"08:30:00",
"03:30:00",
null
]
What can I do or how can I change the SELECT statement so that I also get NULL values in the list?
SELECT startTimeDelta
FROM test
CROSS JOIN JSON_TABLE(val,
'$[*][*].entries[*]' COLUMNS (startTimeDelta TIME PATH '$.startTimeDelta')) jsontable
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=491f0f978d200a8a8522e3200509460e
Do you also have a working idea for MySQL< 8? – Lars
What is max amount of objects in the array on the 2nd level? – Akina
Well it's usually less than 10 – Lars
SELECT JSON_EXTRACT(val, CONCAT('$[0][', num, '].entries[0].startTimeDelta')) startTimeDelta
FROM test
-- up to 4 - increase if needed
CROSS JOIN (SELECT 0 num UNION SELECT 1 UNION SELECT 2 UNION SELECT 3) nums
WHERE JSON_EXTRACT(val, CONCAT('$[0][', num, '].entries[0]')) IS NOT NULL;
https://www.db-fiddle.com/f/xnCCSTGQXevcpfPH1GAbUo/0

Full text search in concrete node in json

I has table "Product" with two columns:
Id - Bigint primary key
data - Jsonb
Here example of json:
{
"availability": [
{
"qty": 10,
"price": 42511,
"store": {
"name": "my_best_store",
"hours": null,
"title": {
"en": null
},
"coords": null,
"address": null,
I insert json to column "data".
Here sql get find "my_best_store"
select *
from product
where to_tsvector(product.data) ## to_tsquery('my_best_store')
Nice. It's work fine.
But I need to find "my_best_store" only in section "availability".
I try this but result is empty:
select *
from product
where to_tsvector(product.data) ## to_tsquery('availability & my_best_store')
Assuming you want to search in the name attribute, you can do the following:
select p.*
from product p
where exists (select *
from jsonb_array_elements(p.data -> 'availability') as t(item)
where to_tsvector(t.item -> 'store' ->> 'name') ## to_tsquery('my_best_store'))
With Postgres 12, you can simplify that to:
select p.*
from product p
where to_tsvector(jsonb_path_query_array(data, '$.availability[*].store.name')) ## to_tsquery('my_best_store')

NodeJS, MySQL - JSON Stringify - Advanced query

I have an object in the table column saved using JSON.stringify and it looks like this:
[{
"id": 1,
"uID": 10
}, {
"id": 2,
"uID": 10
}, {
"id": 3,
"uID": 94
}]
I need a query that will check if a given column contains values e.g.
I want uID = 10 and id = 2 will return
I want uID = 10 and id = 5 will not return it
I want uID = 10 and id = 2, uID = 94 and id = 0 will not return it
(because uID = 94 and id = 0 is not here)
Unless you are querying programmatically where you can parse the JSON and then do the logic, I would recommend something like this:
SELECT * FROM Table WHERE Column LIKE '%"id": 1,"uID": 10%'
The LIKE keyword allows us to use wildcards (%) but still do an exact text match for what we define.
Add a wildcard in the middle, but note that order matters with this strategy.
SELECT * FROM Table WHERE Column LIKE '%"id": 1%"id": 2%'
I need it to work backwards too:] e.g. I have
[{
"id": 1,
"uID": 10
}, {
"id": 2,
"uID": 55
}, {
"id": 3,
"uID": 94
}]
SELECT * FROM Table WHERE Column LIKE '%"uID": 55%"uID": 94%' <- will be working
SELECT * FROM Table WHERE Column LIKE '%"uID": 94%"uID": 55%' <- will be not working
Does not work "back"

Search for a value in a JSON field in MYSQL

I am trying to understand the "new" MYSQL JSON field.
I have this table:
id (int-11, not_null, auto_inc)
customer_id (int-11, not null)
labels (json)
With this data:
id: 1
customer_id: 1
labels: [{"isnew": "no", "tagname": "FOO", "category": "CAT_1", "isdeleted": "no"}, {"isnew": "yes", "tagname": "BAR", "category": "CAT_2", "isdeleted": "no"}]
JSON beautify
[
{
"tagname": "FOO",
"category": "CAT_1",
"isnew": "no",
"isdeleted": "no"
},
{
"tagname": "BAR",
"category": "CAT_2",
"isnew": "yes",
"isdeleted": "no"
}
]
And now I want to SELECT all the customers (by customer_id) in the table that have a specific category and a specific tagname
I tried this one:
SELECT * FROM labels_customers_json
WHERE JSON_SEARCH(labels, 'all', 'BAR') IS NOT NULL
But this is not what I want. This one is searching in every json attribute.
I have seen some examples of JSON_EXTRACT:
SELECT * FROM `e_store`.`products`
WHERE
`category_id` = 1
AND JSON_EXTRACT(`attributes` , '$.ports.usb') > 0
AND JSON_EXTRACT(`attributes` , '$.ports.hdmi') > 0;
SELECT c, c->"$.id", g, n
FROM jemp
WHERE JSON_EXTRACT(c, "$.id") > 1
ORDER BY c->"$.name";
So I tried this
SELECT * FROM labels_customers_json
WHERE JSON_EXTRACT(labels, '$.tagname') = 'BAR'
SELECT labels, JSON_EXTRACT(labels, "$.customer_id"), customer_id
FROM labels_customers_json
WHERE JSON_EXTRACT(labels, "$.customer_id") > 0
You could probably try using SELECT * FROM labels_customers_json WHERE JSON_SEARCH(labels, 'all', "BAR", NULL, "$[*].tagname") is not null - although i cannot say if that is the best way to perform this query.
You can use JSON_SEARCH to search on a specific path too. So you can use the following query:
SELECT *
FROM labels_customers_json
WHERE JSON_SEARCH(labels, 'all', 'BAR', NULL, '$[*].tagname') IS NOT NULL
You can also use JSON_EXTRACT and JSON_CONTAINS together:
SELECT *
FROM labels_customers_json
WHERE JSON_CONTAINS(JSON_EXTRACT(labels, '$[*].tagname'), '["BAR"]') > 0;
You can also use only JSON_CONTAINS to check:
SELECT *
FROM labels_customers_json
WHERE JSON_CONTAINS(labels, '{"tagname":"BAR"}') > 0;
demos: https://www.db-fiddle.com/f/rufrThAQPfXHrK9YyibFSm/2