Home > Blockchain >  Get fields of total and rows as two keys of object in postgreSQL
Get fields of total and rows as two keys of object in postgreSQL

Time:03-28

I have an sql query to get users and total

await db.query({
      text: `with cte as
                (select "id", "createdAt", "deletedAt", "role", "email", "name", "group" from "admin" 
                where (lower("name") like '%' || lower($1) || '%'))
                select * from (table cte
                order by
                    case when $2 = 'desc' then "createdAt" end desc,
                    case when $2 = 'asc' then "createdAt" end asc
                limit $3
                offset $4) sub
                right join (select count(*) from cte) c(total) on true`,
      values: [search, createdAt, limit, offset]
    })

And this query return users as array of objects with total in each user object

[
  {
    id: '135e8d05-4723-4dd7-9ae0-6e10626799f3',
    createdAt: 2022-03-27T08:34:37.636Z,
    deletedAt: null,
    role: 'root',
    email: '[email protected]',
    name: 'Test Name',
    group: 'Test Group,
    total: '4'
  }
]

What i should to do to get something like that

{
   total: 4,
   users: [
      {
        id: '135e8d05-4723-4dd7-9ae0-6e10626799f3',
        createdAt: 2022-03-27T08:34:37.636Z,
        deletedAt: null,
        role: 'root',
        email: '[email protected]',
        name: 'Test Name',
        group: 'Test Group,
      }
   ]
}

CodePudding user response:

you can use row_to_json & json_agg to convert all results to a json list of objects.

This won't give you exactly what you desire, but close. The query below should return results in the format [{total: xxx, users: [user-records]}], so in your application code you have to get the first row returned by the database query.

with cte as (
  select 
    "id"
  , "createdAt"
  , "deletedAt"
  , "role"
  , "email"
  , "name"
  , "group" 
  from "admin" 
  where (lower("name") like '%' || lower($1) || '%')
)
select * 
from (
  select 
    json_agg(
      row_to_json(cte.*)
      order by 
        case
          when $2 = 'desc' then "createdAt" desc
          when $2 = 'asc' then "createdAt" asc
        end   
    ) users 
  from cte
  order by
    case 
      when $2 = 'desc' then "createdAt" desc
      when $2 = 'asc' then "createdAt" asc
    end
  limit $3
  offset $4
) sub
right join (
  select count(*) from cte
) c(total) 
        on true

CodePudding user response:

As I understand, you generate JSON data on PostgreSQL. In your query, you didn't write JSON generation codes. Ok, I wrote two samples for you:

Sample 1:

with cte as
(
    select "id", "createdAt", "deletedAt", "role", "email", "name", "group" from "admin" 
    where (lower("name") like '%' || lower($1) || '%')
)
select jsonb_agg(row_to_json(t1)) from (
    select * from (table cte
    order by
        case when $2 = 'desc' then "createdAt" end desc,
        case when $2 = 'asc' then "createdAt" end asc
    limit $3
    offset $4) sub
    right join (select count(*) from cte) c(total) on true
) t1 

This query results

[
  {
    id: '135e8d05-4723-4dd7-9ae0-6e10626799f3',
    createdAt: 2022-03-27T08:34:37.636Z,
    deletedAt: null,
    role: 'root',
    email: '[email protected]',
    name: 'Test Name',
    group: 'Test Group,
    total: '4'
  }
]

Sample 2: (You needed)

with cte as
(
    select "id", "createdAt", "deletedAt", "role", "email", "name", "group" from "admin" 
    where (lower("name") like '%' || lower($1) || '%')
)
select row_to_json(t1) from (
    select 
        c.total,  
        jsonb_agg(row_to_json(sub)) as "users"
    from (table cte
    order by
        case when $2 = 'desc' then "createdAt" end desc,
        case when $2 = 'asc' then "createdAt" end asc
    limit $3
    offset $4) sub
    right join (select count(*) from cte) c(total) on true
    group by c.total 
) t1 

This query results in your needed format:

{
   total: 4,
   users: [
      {
        id: '135e8d05-4723-4dd7-9ae0-6e10626799f3',
        createdAt: 2022-03-27T08:34:37.636Z,
        deletedAt: null,
        role: 'root',
        email: '[email protected]',
        name: 'Test Name',
        group: 'Test Group,
      }
   ]
}
  • Related