Последовательная установка внешних ключей при создании из вложенного объекта - PullRequest
0 голосов
/ 12 февраля 2020

Я использую PostgreSQL в качестве базы данных. У меня есть две модели, RateSection и Shop, где в магазине есть много RateSections, и каждый RateSection принадлежит одному магазину

export const Shop = <ShopModelStatic>db.define(
    'shop',
    {
        shopUrl: {
            type: sequelize.STRING,
            allowNull: false
        },
        active: {
            type: sequelize.BOOLEAN,
            allowNull: false
        }
    },
    {
        underscored: true
    }
);

export const RateSection = <RateSectionModelStatic>db.define(
    'rate_section',
    {
        minWeight: {
            type: sequelize.FLOAT,
            allowNull: false
        },
        maxWeight: {
            type: sequelize.FLOAT,
            allowNull: false
        },
        price: {
            type: sequelize.FLOAT,
            allowNull: false
        },
        freeShippingMinPrice: {
            type: sequelize.FLOAT
        },
        minShippingDays: {
            type: sequelize.INTEGER
        },
        maxShippingDays: {
            type: sequelize.INTEGER
        },
    },
    {
        underscored: true
    }
);

Shop.hasMany(RateSection);
RateSection.belongsTo(Shop);

Они правильно определены в таблицах базы данных. В настоящее время, когда я хочу вставить новый RateSection с соответствующим отношением, я вынужден сделать это

RateSection.create(rateSection).then((newRateSection: any) => {
                newRateSection.setShop(shop);
                return newRateSection.save();
            });

Моя главная проблема с этим методом заключается в том, что он делает несколько вызовов для каждого RateSection.create. Я хочу, чтобы иметь возможность просто передать вложенный объект в RateSection.create, как это

const rateSection {
  minWeight: 1,
  maxWeight: 2,
  ...whateverprops,
  shop: {
    id: 1,
  }
}

Когда я передаю этот вложенный объект, он создает раздел скорости, но внешний ключ установлен на ноль, я пытался это без удачи

RateSection.create(rateSection, { include: [Shop] });

Можете ли вы помочь брату?

Ответы [ 2 ]

0 голосов
/ 02 марта 2020

Никогда этого не достиг. Наконец-то перешел на TypeORM, намного, НАМНОГО лучше.

0 голосов
/ 13 февраля 2020

должно работать. Вот рабочий пример:

index.ts:

import { sequelize as db } from '../../db';
import sequelize, { Model, BuildOptions } from 'sequelize';

interface ShopModel extends Model {}
type ShopModelStatic = typeof Model & {
  new (values?: object, options?: BuildOptions): ShopModel;
};

interface RateSectionModel extends Model {}
type RateSectionModelStatic = typeof Model & {
  new (values?: object, options?: BuildOptions): RateSectionModel;
};

export const Shop = <ShopModelStatic>db.define(
  'shop',
  {
    shopUrl: {
      type: sequelize.STRING,
      allowNull: false,
    },
    active: {
      type: sequelize.BOOLEAN,
      allowNull: false,
    },
  },
  {
    underscored: true,
  },
);

export const RateSection = <RateSectionModelStatic>db.define(
  'rate_section',
  {
    minWeight: {
      type: sequelize.FLOAT,
      allowNull: false,
    },
    maxWeight: {
      type: sequelize.FLOAT,
      allowNull: false,
    },
    price: {
      type: sequelize.FLOAT,
      allowNull: false,
    },
    freeShippingMinPrice: {
      type: sequelize.FLOAT,
    },
    minShippingDays: {
      type: sequelize.INTEGER,
    },
    maxShippingDays: {
      type: sequelize.INTEGER,
    },
  },
  {
    underscored: true,
  },
);

Shop.hasMany(RateSection);
RateSection.belongsTo(Shop);

(async function test() {
  try {
    await db.sync({ force: true });
    const rateSection = {
      minWeight: 1,
      maxWeight: 2,
      price: 100,
      shop: {
        id: 1,
        shopUrl: 'https://stackoverflow.com/',
        active: true,
      },
    };
    await RateSection.create(rateSection, { include: [Shop] });
  } catch (error) {
    console.log(error);
  } finally {
    await db.close();
  }
})();

После выполнения вышеуказанного кода проверьте записи данных в базе данных:

node-sequelize-examples=# select * from "shop";
 id |          shop_url          | active
----+----------------------------+--------
  1 | https://stackoverflow.com/ | t
(1 row)

node-sequelize-examples=# select * from "rate_section";
 id | min_weight | max_weight | price | free_shipping_min_price | min_shipping_days | max_shipping_days | shop_id
----+------------+------------+-------+-------------------------+-------------------+-------------------+---------
  1 |          1 |          2 |   100 |                         |                   |                   |       1
(1 row)

Внешний ключ shop_id добавляется к rate_section, как и ожидалось. Отладочное сообщение выполнения кода:

{ POSTGRES_HOST: '127.0.0.1',
  POSTGRES_PORT: '5430',
  POSTGRES_PASSWORD: 'testpass',
  POSTGRES_USER: 'testuser',
  POSTGRES_DB: 'node-sequelize-examples' }
Executing (default): DROP TABLE IF EXISTS "rate_section" CASCADE;
Executing (default): DROP TABLE IF EXISTS "shop" CASCADE;
Executing (default): DROP TABLE IF EXISTS "shop" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "shop" ("id"   SERIAL , "shop_url" VARCHAR(255) NOT NULL, "active" BOOLEAN NOT NULL, PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'shop' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): DROP TABLE IF EXISTS "rate_section" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "rate_section" ("id"   SERIAL , "min_weight" FLOAT NOT NULL, "max_weight" FLOAT NOT NULL, "price" FLOAT NOT NULL, "free_shipping_min_price" FLOAT, "min_shipping_days" INTEGER, "max_shipping_days" INTEGER, "shop_id" INTEGER REFERENCES "shop" ("id") ON DELETE SET NULL ON UPDATE CASCADE, PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'rate_section' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): INSERT INTO "shop" ("id","shop_url","active") VALUES ($1,$2,$3) RETURNING *;
Executing (default): INSERT INTO "rate_section" ("id","min_weight","max_weight","price","shop_id") VALUES (DEFAULT,$1,$2,$3,$4) RETURNING *;

Исходный код: https://github.com/mrdulin/node-sequelize-examples/tree/master/src/examples/stackoverflow/60196739

...