Lets say I have a model named Item
, which contains a JSONB field data
. One of the records has the following JSON object stored there:
{
"name": "hello",
"nested_object": {
"nested_name": "nested"
},
"nested_list": [
{
"nested_key": "one"
},
{
"nested_key": "two"
}
]
}
I can find this record by filtering on the name
field as such:
Session().query(Item).filter(Item.data["name"] == "hello")
I can find this record by filtering on the nested object likewise as such:
Session().query(Item).filter(Item.data[("nested_object","nested_name")] == "hello")
However I am struggling to find a way to find this record by filtering on the value of the item stored within the nested list.
In other words I want to find the record above if the user has provided value "one", and I know to look for it in the key nested_key
within the nested_list
.
Is it possible to achieve this with SQLAlchemy filters available?
SQLAlchemy's JSONB
type has the contains()
method for the @>
operator in Postgresql. The @>
operator is used to check if the left value contains the right JSON path/value entries at the top level. In your case
data @> '{"nested_list": [{"nested_key": "one"}]}'::jsonb
Or in python
the_value = 'one'
Session().query(Item).filter(Item.data.contains(
{'nested_list': [{'nested_key': the_value}]}
))
The method converts your python structure to suitable JSON string for the database.
In Postgresql 12 you can use the JSON path functions:
import json
Session().query(Item).\
filter(func.jsonb_path_exists(
Item.data,
'$.nested_list[*].nested_key ? (@ == $val)',
json.dumps({"val": the_value})))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With