Search code examples
sqlpostgresqltags

PostgreSQL - Select items with certain tags, but keep all tags in the result


I have a problem with my tag search where the database correctly returns the images containing the tags, BUT all of the other tags are stripped. I store all of the tags in a separate table "tag map".

This is my result for search "tag1" (image actually has more tags than just tag1):

[{"postID": 1, "images": {"imageID": 1, "tags": ["tag1"]}}]

This is the result that I want for search "tag1":

[{"postID": 1, "images": {"imageID": 1, "tags": ["tag1", "tag2", "tag3"]}}]

This is the query that generates the first result:

WITH image_tags AS (
  SELECT images."post id", json_build_object (
    'imageID', images."image id",
    'tags', json_agg("tag map".tag)
  ) AS image,
  FROM images
  JOIN "tag map" ON images."image id" = "tag map"."image id"
  WHERE "tag map".tag = ALL ($1)
  GROUP BY images."post id", images."image id"
)
SELECT posts."post id" AS "postID", json_agg(image_tags.image) AS images 
FROM posts
JOIN image_tags ON posts."post id" = image_tags."post id"
GROUP BY posts."post id"

Solution

  • The answer is group it into a subquery and use WHERE after. I changed my table structure so the query is a bit different than in OP.

    SELECT * FROM (
      SELECT posts.*, json_agg(DISTINCT images.*) AS images, array_agg(DISTINCT "tag map".tag) AS tags
      FROM posts
      JOIN images ON posts."postID" = images."postID"
      JOIN "tag map" ON posts."postID" = "tag map"."postID"
      GROUP BY posts."postID"
    ) AS posts
    WHERE tags @> $1