I came across a very peculiar problem the other day. I had a Postgres
database and one of the tables had an attribute object_changes
which was yaml
. Now, the data stored in this attribute was of whatever fields getting updated in a transaction.
I had to check when a given field
changed to a particular value. Thus if a record had a column kyc_status
which had a value of pending
and I needed to track when this value got changed to submitted
. I decided to convert this yaml
to json
first, I have described my approach here.
Querying on json
is not quite straight forward. After lots of trial and error, I came across a working solution like this:
SELECT "versions".* FROM "versions" WHERE (
(
object_changes::jsonb @> '{"kyc_status": ["pending", "created"]}'
OR object_changes::jsonb @> '{"kyc_status": ["received", "created"]}'
)
AND item_type = 'Investor'
AND event = 'update'
)
Here I am casting the object_changes
as jsonb
explicitely, and then querying on that json if it contained a key
kycs_status
which was changed to created
from pending
or from received
.
The object looked something like below:
#<PaperTrail::Version:0x000000000d3d6fc8> {
:id => 2567881,
:item_type => "Investor",
:item_id => x,
:event => "update",
:whodunnit => nil,
:object => nil,
:created_at => Fri, 02 Nov 2018 14:24:52 IST +05:30,
:object_changes => nil,
:transaction_id => 2567881,
:object => {
"id" => 23,
"created_at" => "2016-08-08T05:22:20.105Z",
"kyc_status" => "pending",
"updated_at" => "2018-09-13T10:14:07.879Z"
},
:object_changes => {
"kyc_status" => [
[0] "pending",
[1] "blocked"
]
}
}