2016-05-28 3 views
1

Я хочу сделать что-то, что я не совсем уверен.Выход многомерного массива как JSON

Я начинаю с базой данных, подобными этим:

create table events (id int primary key, common int, location text); 

insert into events values (2, 100, 'Something'); 
insert into events values (3, 100, 'Something'); 
insert into events values (4, 100, 'Something'); 
insert into events values (5, 200, 'Something'); 
insert into events values (6, 200, 'Something'); 
insert into events values (7, 200, 'Something'); 
insert into events values (8, 200, 'Something'); 
insert into events values (9, 100, 'Something'); 
insert into events values (10, 200, 'Something'); 
insert into events values (11, 200, 'Something'); 
insert into events values (12, 200, 'Something'); 
insert into events values (13, 300, 'Something'); 
insert into events values (14, 200, 'Something'); 
insert into events values (15, 300, 'Something'); 
insert into events values (16, 200, 'Something'); 
insert into events values (17, 300, 'Something'); 

И я хочу, чтобы получить данные, сгруппированные в объект с common значений в качестве ключей:

{ 
    "100":{ 
    "2":"Something", 
    "3":"Something", 
    "4":"Something", 
    "9":"Something"}, 
    "200":{ 
    "5":"Something", 
    "6":"Something", 
    "7":"Something", 
    "8":"Something"}, 
    "300":{ 
    "13":"Something", 
    "15":"Something", 
    "17":"Something", 
    "18":"Something"} 
} 

Я могу, конечно, сделать он с несколькими выборами, но один выбор будет полезен.

Любая помощь будет фантастической! Благодаря!

ответ

2

Для PostgreSQL любой версии

Важной частью здесь является правильным SELECT, что бы сгруппировать данные таким образом, чтобы сделать его легко превратить в свой словарь типа:

SELECT * FROM events GROUP BY common, id ORDER BY common 

Он производит следующие результаты:

2 100 "Something" 
3 100 "Something" 
4 100 "Something" 
9 100 "Something" 
5 200 "Something" 
6 200 "Something" 
7 200 "Something" 
8 200 "Something" 
10 200 "Something" 
11 200 "Something" 
12 200 "Something" 
14 200 "Something" 
16 200 "Something" 
13 300 "Something" 
15 300 "Something" 
17 300 "Something" 

В этот момент, независимо от того, на каком языке y ou использовать для вашего серверного кода, превращая его в словарь с common, поскольку ключи становятся легкой задачей.

Например, в Node.js вы можете сделать это следующим образом:

function transform(rows) { 
    var key, obj, result = {}; 
    rows.forEach(function (r) { 
     if (r.common !== key) { 
      if (obj) { 
       result[key] = obj; 
      } 
      obj = {}; 
      key = r.common; 
     } 
     obj[r.id] = r.location; 
    }); 
    if (obj) { 
     result[key] = obj; 
    } 
    return result; 
} 

Для полного примера, используя pg-promise:

db.query('SELECT * FROM events GROUP BY common, id ORDER BY common') 
    .then(data=> { 
     console.log(transform(data)); 
    }) 
    .catch(error=> { 
     console.log(error); 
    }); 

Выходы:

{ 
    '100': { 
     '2': 'Something', 
     '3': 'Something', 
     '4': 'Something', 
     '9': 'Something' 
    }, 
    '200': { 
     '5': 'Something', 
     '6': 'Something', 
     '7': 'Something', 
     '8': 'Something', 
     '10': 'Something', 
     '11': 'Something', 
     '12': 'Something', 
     '14': 'Something', 
     '16': 'Something' 
    }, 
    '300': { 
     '13': 'Something', 
     '15': 'Something', 
     '17': 'Something' 
    } 
} 

Для PostgreSQL 9.4 и более поздних версий

С PostgreSQL 9.4, а затем вы можете сделать все это в SQL, используя функцию json_object_agg:

SELECT json_object_agg(common, j ORDER BY common) 
FROM (SELECT common, json_object_agg(id, location order by id) 
AS j FROM events GROUP BY common) t; 

Сравнение производительности

Сравнение производительности стандарта против нового подхода не легко , но учтите следующее:

У нас есть простой сингл select + очень простое и быстрое преобразование по сравнению с двойной выборкой + двойной агрегацией на сервере. Поэтому я не удивлюсь, если старое решение превзойдет новое.

+1

Да, я думал, что это лучший способ сделать это, спасибо за код: D Я делаю это в PHP, поэтому код не тот, что мне нужен, но я уверен, что смогу перевести Это. Благодаря! – Steve

+1

@Steve См. Обновление для решения pure-SQL;) –

Смежные вопросы