Как подготовить объекты и массивы JSON из связанных таблиц базы данных? - PullRequest
0 голосов
/ 24 сентября 2019

Я работаю над простым REST API в узле и хочу создать запрос в SQLite, который будет возвращать все продукты вместе с их возможными параметрами.

Это моя база данных:

BEGIN TRANSACTION;
PRAGMA foreign_keys = OFF;
CREATE TABLE IF NOT EXISTS "product_options" (
    "id"    INTEGER,
    "product_id"    INTEGER,
    "name"  TEXT NOT NULL,
    "value" TEXT NOT NULL,
    PRIMARY KEY("id"),
    FOREIGN KEY("product_id") REFERENCES "products"("id")
);
CREATE TABLE IF NOT EXISTS "products" (
    "id"    INTEGER,
    "name"  TEXT NOT NULL,
    "brand_id"  INTEGER,
    PRIMARY KEY("id")
);
CREATE TABLE IF NOT EXISTS "brands" (
    "id"    INTEGER,
    "name"  TEXT NOT NULL,
    PRIMARY KEY("id")
);
INSERT INTO "product_options" VALUES (1,1,'color','black');
INSERT INTO "product_options" VALUES (2,1,'color','white');
INSERT INTO "product_options" VALUES (3,2,'color','indigo');
INSERT INTO "product_options" VALUES (4,3,'color','black');
INSERT INTO "product_options" VALUES (5,1,'size','9');
INSERT INTO "products" VALUES (1,'t-shirt',1);
INSERT INTO "products" VALUES (2,'jeans',3);
INSERT INTO "products" VALUES (3,'shoes',2);
INSERT INTO "products" VALUES (4,'shirt',NULL);
INSERT INTO "brands" VALUES (1,'acme');
INSERT INTO "brands" VALUES (2,'wonka');
INSERT INTO "brands" VALUES (3,'gekko');
INSERT INTO "brands" VALUES (4,'stark');
PRAGMA foreign_keys = ON;
COMMIT;

И это пример вывода JSON, который должна генерировать моя конечная точка API при запросе продукта:

{
    "id": 1,
    "name": "t-shirt",
    "brand": "acme",
    "options": {
        "color": ["black", "white"],
        "size": ["9"]
    }
}

До сих пор я придумал первую часть запроса, но не могу понятьКак вывести параметры:

SELECT DISTINCT
    products.id,
    products.name,
    brands.name AS brand,
    product_options.value AS option_value
FROM products
INNER JOIN brands on brands.id = products.brand_id
INNER JOIN product_options on product_options.product_id = products.id
WHERE products.id = 1

Возвращает следующий результат:

id  name    brand   option_value
1   t-shirt acme    black
1   t-shirt acme    white
1   t-shirt acme    9

Тем не менее, я хочу получить следующий вывод:

id  name    brand   color           size
1   t-shirt acme    black, white    9

Конечно,запрос должен быть «динамическим», поэтому любые другие опции, добавленные к продукту в будущем, также должны быть возвращены, например:

id  name    brand   color           size    condition
1   t-shirt acme    black, white    9       new, used

Есть идеи, как мне этого добиться?Я знаю, что могу просто создать две конечные точки, одну для получения списка продуктов, а другую для возврата его параметров, но наличие всего в одном документе кажется более удачным решением.

Любая помощь будет высоко оценена, спасибо!

1 Ответ

1 голос
/ 25 сентября 2019

Вы можете использовать стандартный JSON1 модуль и несколько агрегатных подзапросов для генерации JSON непосредственно из sqlite:

SELECT
  json_object('id', p.id
            , 'name', p.name
            , 'brand', b.name
            , 'options', (SELECT json_group_object(name, ja)
                          FROM (SELECT po.name
                                     , json_group_array(po.value) AS ja
                                FROM product_options AS po
                                WHERE po.product_id = p.id
                                GROUP BY po.name)))
FROM products AS p
JOIN brands AS b ON p.brand_id = b.id
WHERE p.id = 1;
{"id":1,"name":"t-shirt","brand":"acme","options":{"color":["black","white"],"size":["9"]}}

Для достижения наилучших результатов добавьтеиндекс по product_options(product_id, name).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...