0

In a Postgresql (13+), a users table has a JSONB[] column (notifications) containing user notification. Notifications are populated by a simple dictionary, resulting in the following array:

[
  { 
    "notification_id": "c20da296", # abbreviating UUID4
    "level": "info",
    "timestamp": ...,
    "content": ...
  },

  .. more notifications ..
]

When a user dismisses a notification, i'd like to remove it from the array, using the notification's id (while leaving the other notifications). Many resources show how to deal with a JSONB nested structure (e.g., here) or across multiple users (e.g., here). Is there a way to achieve this, maybe using the - operator in some way? I'm expecting something along the following:

UPDATE users SET notifications - `{"notification_id": "c20da296"}` 
WHERE user_id = "<user_uuid4>";

note: the user's identifier is known, there is no need to traverse all users to select for the relevant notification_id.

2
  • Looks like someone else asked a question similar to this before. They said that they were able to figure out how to do it for just one row and needed help doing it for multiple rows. The accepted answer includes an example showing it done for either one row or multiple rows: stackoverflow.com/questions/40285583/… Commented Sep 21, 2021 at 0:13
  • @Matt, see in original post - in the question you're linking to the column is structured ('name', 'type', 'attributes'), under properties column. My column is an array, not a dictionary. Commented Sep 21, 2021 at 0:21

1 Answer 1

0

Use jsonb_path_query_array function with a "not equal" condition in the path.
It returns all JSON items returned by the JSON path for the specified JSON value, as a JSON array

Here's an example

UPDATE users 
SET notifications = jsonb_path_query_array(notifications, '$ ? (@.notification_id != "<notification_id_for_removal>")')
WHERE user_id = "<user_uuid4>";
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.