From: | Dmitry Dolgov <9erthalion6(at)gmail(dot)com> |
---|---|
To: | PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org> |
Subject: | Proposal about a "deep" versions for some jsonb functions |
Date: | 2017-07-20 09:43:27 |
Message-ID: | CA+q6zcU+gy1+dxQD09MSz8Zwqq+sPPfS-6GYKmyNqGVQDFeQbg@mail.gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
Hi
As far as I know, since 9.5 we're missing some convenient features, namely a
deepversion of `jsonb_concat` and `jsonb_minus`. There are already few
feature
requests about `jsonb_minus` (see [1], [2]) and a lot of confusion and
requests
about a deep version of `jsonb_concat`. From my point of view they're pretty
much related, so I want to propose the following description for this
functionality and eventually implement it.
# jsonb_minus
```
jsonb_minus(jsonb, jsonb, deep=False)
```
Looks like we have to abandon "-" operator for that purpose (see a concern
about that in this thread [2]).
In general this functionality is something like the relative complement for
two
jsonb objects. Basically we're taking all the paths inside all jsonb objects
and remove duplicated paths from the left one. Of course an actual
implementation may be different, but I think it's a nice way of thinking
about
this logic.
Here are few examples, where "->" is an operation to get an actual value,
".->" - an operation to get a next key, "#->" an operation to get a value
from
an array ("-" operator is just for the sake of readability):
------------------------------------------------------------------------------
{"a": 1} - {"a": 1}
=> null
paths:
a -> 1
a -> 1
------------------------------------------------------------------------------
{"a": 1} - {"a": 2}
=> {"a": 1}
paths:
a -> 1
a -> 2
------------------------------------------------------------------------------
{"a": 1} - {"a": {"b": 1}}
=> {"a": 1}
paths:
a ->
a -> .b -> 1
------------------------------------------------------------------------------
{"a": 1, "b": {"c": 2}} - {"b": 1, "b": {"c": 3}}
=> {"b": {"c": 2}}
paths:
a -> 1
b .-> c -> 2
b -> 1
b .-> c -> 3
------------------------------------------------------------------------------
{"a": {"b": 1}} - {"a": {"b": 1}}
=> null
paths:
a .-> b -> 1
a .-> b -> 1
------------------------------------------------------------------------------
{"a": {"b": 1, "c": 2}} - {"a": {"b": 1}}
=> {"a": {"b": 1}}
paths:
a .-> b -> 1
a .-> c -> 2
a .-> b -> 1
------------------------------------------------------------------------------
{"a": {
"b": {"b1": 1},
"c": {"c2": 2}
}}
-
{"a": {
"b": {"b1": 1},
"c": {"c2": 3}
}}
=> {"a": {"c": {"c2": 2}}
paths:
a .-> b .-> b1 -> 1
a .-> c .-> c2 -> 2
a .-> b .-> b1 -> 1
a .-> c .-> c2 -> 3
------------------------------------------------------------------------------
{"a": [1, 2, 3]} - {"a": [1, 2]}
=> {"a": [3]}
paths:
a #-> 1
a #-> 2
a #-> 3
a #-> 1
a #-> 2
------------------------------------------------------------------------------
{"a": [{"b": 1}, {"c": 2}]} - {"a": [{"b": 1}, {"c": 3}]}
=> {"a": [{"c": 3}]}
paths:
a #-> b -> 1
a #-> c -> 2
a #-> b -> 1
a #-> c -> 3
But judging from the previous discussions, there is a demand for a bit
different behavior, when `jsonb_minus` is operating only on the top level of
jsonb objects. For that purpose I suggest introducing a flag `deep`, that
should be false by default (as for `jsonb_concat`), that will allow to
enable a
"deep logic" (a.k.a relative complement) I described above. With
`deep=False`
this function will behave similar to `hstore`:
{"a": 1, "b": {"c": 2}} - {"a": 1, "b": {"c": 3}}
=> {"a": 1}
# jsonb_concat
We already have this function implemented, but a "deep" mode is missing.
```
jsonb_concat(jsonb, jsonb, deep=False)
```
Basically we're taking all the paths inside all jsonb objects and override
duplicated paths in the left one, then add all unique paths from right one
to
the result.
Here are few examples for deep mode ("||" operator is just for the sake of
readability):
------------------------------------------------------------------------------
{"a": 1, "b": {"c": 2}} || {"a": 1, "b": {"d": 3}}
=> {"a": 1, "b": {"c": 2, "d": 3}}
paths:
a -> 1
b .-> c -> 2
a -> 1
b .-> d -> 3
------------------------------------------------------------------------------
{"a": 1, "b": {"c": 2}} || {"a": 1, "b": {"c": 3}}
=> {"a": 1, "b": {"c": 3}}
paths:
a -> 1
b .-> c -> 2
a -> 1
b .-> c -> 3
------------------------------------------------------------------------------
{"a": [1, 2, 3]} || {"a": [3, 4]}
=> {"a": [1, 2, 3, 4]}
paths:
a #-> 1
a #-> 2
a #-> 3
a #-> 3
a #-> 4
What do you think about that?
[1]:
https://www.postgresql.org/message-id/flat/CAHyXU0wtJ%2Bi-4MC5FPVc_oFu%2B3-tQVC8u04GmMNwYdPEAX1XSA%40mail(dot)gmail(dot)com#CAHyXU0wtJ+i-4MC5FPVc_oFu+3-tQVC8u04GmMNwYdPEAX1XSA(at)mail(dot)gmail(dot)com
[2]:
https://www.postgresql.org/message-id/flat/CAHyXU0wm0pkX0Gvzb5BH2jUAA_%3DswMJmyYuhBWzgOjfKxdrKfw%40mail(dot)gmail(dot)com#CAHyXU0wm0pkX0Gvzb5BH2jUAA_=swMJmyYuhBWzgOjfKxdrKfw(at)mail(dot)gmail(dot)com
From | Date | Subject | |
---|---|---|---|
Next Message | Thomas Munro | 2017-07-20 11:08:50 | Re: Causal reads take II |
Previous Message | Fabien COELHO | 2017-07-20 09:17:50 | Re: Adding -E switch to pg_dumpall |