Vyhledávání na webu

node.js - Sequelize asociace nefungují s Typescriptem


Poskytnu nějaký kód, protože může být těžké sledovat, co se děje. V podstatě moje Express API nevrací žádná spojení, i když moje databáze si myslí, že existují.

Stručně a rychle: Snažím se získat asociaci mezi dvěma modely Users a Donations, jeden-k-mnoha.

Zde je můj uživatelský model (zjednodušený):

import { Sequelize, DataTypes, Model, BuildOptions, Optional, Association, } from "sequelize";

// These are all the attributes in the User model
export interface UserAttributes {
    id: number;
    firstName: string;
    lastName: string;
    createdAt?: Date;
    updatedAt?: Date;
}

// Optional properties, sequelize has the ability to fill these in itself
interface UserCreationAttributes
    extends Optional<
        UserAttributes,
        "id"
    > {}

// Creates the final type interface for the UserModel
export interface UserModel
    extends Model<UserAttributes, UserCreationAttributes>,
        UserAttributes {}

// Creates the User class as an extended type of a general model and UserModel
export class User extends Model<UserModel, UserAttributes> {
    // Public properties
    public id!: number;
    public firstName!: string;
    public lastName!: string;

    // Timestamps
    public readonly createdAt!: Date;
    public readonly updatedAt!: Date;

    // Associations
    public static associations: {
        donations: Association<User, Donation>;
    };
}

// Creates a static type used for our factory function
export type UserStatic = typeof Model & {
    new (values?: object, options?: BuildOptions): UserModel;
};

// This function is responsible for generating the "User" model
export function userFactory(sequelize: Sequelize): UserStatic {
    return <UserStatic>sequelize.define(
        "users",
        {
            id: {
                type: DataTypes.INTEGER,
                autoIncrement: true,
                primaryKey: true,
            },
            firstName: {
                type: new DataTypes.STRING(128),
                allowNull: false,
                validate: { notEmpty: true },
            },
            lastName: {
                type: DataTypes.STRING,
                allowNull: false,
                validate: { notEmpty: true },
            },
        });
    }

Dárcovský model je nastaven z velké části stejným způsobem, nechci vás zaplavovat kódem, takže přejdu rovnou k části, kde provádím asociace.

// Import the factory functions and sequelize instance, called "db" here
import { donationFactory } from "./Donation";
import { userFactory } from "./User";
import { db } from "../db";

// The Factory functions expect a Sequelize instance as a parameter
const User = userFactory(db);
const Donation = donationFactory(db);
const DonationsRecipients = donationsRecipientsFactory(db);

// Associations
Donation.belongsTo(User);
User.hasMany(Donation);

// Export model
export const model = {
    Donation,
    DonationsRecipients,
    User,
};

Dobře, takže můžete vidět, že zde deklaruji velmi jednoduchý vztah Jeden-k-Mnoha mezi modely Donation a User. Níže vám ukážu svůj kód pro mou express trasu.

// Get all donors
userGetRoutes.get("/donors", async (req, res, next) => {
    try {
        const users = await User.findAll({
            where: { isDonor: true },
            include: [{ model: Donation }],
        });
        res.status(200).send(users);
    } catch (error) {
        next(error);
    }
});

Ale já dostanu jen toto!!! Zahrnuté dary tam nejsou... Nemohu se dostat k objektům darů

A co je ještě divnější, je, že Postico si myslí, že VZTAH existuje. Poznáte to podle toho, že když kliknete na malou tabulku v mém modelu Donation, objeví se propojený uživatel (Monica Moneybags).

Tak... co se děje??

EDIT: Dobře, takže jsem udělal nějaký pokrok. Podařilo se mi, aby uživatelské instance mohly volat „getDonations()“ a další magické metody, které skutečně vracejí dary.

Abych to udělal, upravil jsem své třídy UserModel a User takto:

import {
    Sequelize,
    DataTypes,
    Model,
    BuildOptions,
    Optional,
    Association,
    HasManyGetAssociationsMixin,
    HasManyAddAssociationMixin,
    HasManyHasAssociationMixin,
    HasManyCountAssociationsMixin,
    HasManyCreateAssociationMixin,
} from "sequelize";

/ Creates the final type interface for the UserModel
export interface UserModel
    extends Model<UserAttributes, UserCreationAttributes>,
        UserAttributes {
    donations: DonationModel[];
    getDonations(): HasManyGetAssociationsMixin<Donation>; // Note the null assertions!
    addDonation(): HasManyAddAssociationMixin<Donation, number>;
    hasDonation(): HasManyHasAssociationMixin<Donation, number>;
    countDonations(: HasManyCountAssociationsMixin;
    createDonation(): HasManyCreateAssociationMixin<Donation>;
}

// Creates the Donation classs as an extended type of a general model and UserModel
export class User extends Model<UserModel, UserAttributes> {
    // Public properties
    public id!: number;
    public firstName!: string;
    public lastName!: string;

    // Timestamps
    public readonly createdAt!: Date;
    public readonly updatedAt!: Date;

    // Associations
    //
    // Since TS cannot determine model association at compile time
    // we have to declare them here purely virtually
    // these will not exist until `Model.init` was called.
    public getDonations!: HasManyGetAssociationsMixin<Donation>; // Note the null assertions!
    public addDonation!: HasManyAddAssociationMixin<Donation, number>;
    public hasDonation!: HasManyHasAssociationMixin<Donation, number>;
    public countDonations!: HasManyCountAssociationsMixin;
    public createDonation!: HasManyCreateAssociationMixin<Donation>;

    public readonly donations?: Donation[]; // Note this is optional since it's only populated when explicitly requested in code

    public static associations: {
        donations: Association<User, Donation>;
    };
}

Přesto však inkluze nefungují na volaných jako:

const users = await User.findOne({
            where: { isDonor: true },
            include: [{ model: Donation }],
        });

Vrací to jen prázdné pole v vlastnosti „donations“ :/