Sequelize map model to existing class that already extends a base class - class

I may be missing something obvious but in the following (using MDN class examples) how can the Dog class, which already extends Animal, map/relate to the sequelize model such that I can create a new instance of Dog and save it to the database? I was expecting similar to how SQLAlchemy handles mapping with map_imperatively()
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize('sqlite::memory:');
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
constructor(name) {
super(name);
}
speak() {
console.log(`${this.name} barks.`);
}
}
let d = new Dog('Mitzie');
d.speak();
const DogModel = sequelize.define('Dog', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
name: {
type: DataTypes.STRING,
allowNull: false
}
});

Related

Recursive mongoose schema does not result in correct object stores

I have a recursive model schema defined in a schema which uses the add() method in the Schema class to incrementally build the schema. It seems to build the paths correctly as shown when I print out the paths. However, when I use the Model defined to store the object in the database, it is missing the inner BNode. Here is a definition of the schema:
import mongoose from 'mongoose';
const BNodeSchema = new mongoose.Schema({
bValue: { type: [Number] },
id: String,
})
const RValue = {
rId: String,
value: Number
}
const ANodeSchema = new mongoose.Schema({
type: {
id: String,
rValues: {
type: Map,
of: RValue
},
}
})
const QuestSchema = new mongoose.Schema({
type: {
_id: { type: String, },
aNode: ANodeSchema,
bNodes: [BNodeSchema],
url: {
type: String
},
id: {
type: String
}
},
},
{ id: false }
)
ANodeSchema.add({ quest: QuestSchema });
const QuestNodeSchema = new mongoose.Schema({
_id: { type: String, unique: true },
quests: { type: [QuestSchema] },
}, {
id: false
})
export const QuestModel = mongoose.model('QuestModel', QuestNodeSchema);
QuestNodeSchema.eachPath(function(path:any) {
console.log(path);
});
{
_id: 12223,
quests:[
{
id: 'Quest-111-111' ,
aNode: {
id: 'A222222',
rValues: {
rId: 'RR1222',
value: 44422
},
quest:{
url: 'https://deptio-opcom',
id: '22222-QST',
bNodes:[{
bValue: 'B22190',
value: 22085
}]
}
}
}
]
}
I have included a sample of the json I am storing in the database. I use a class, not included for brevity to create the equivalent JSON object in the final format to be stored. My feeling is that there is something not quite right with my schema definition. I would be most grateful if someone could help me figure out what I am missing in my definition. Thanks a lot

How to accept multiple objects into an array NestJS

I have a feedbackQuestion schema which takes (title: string, subtitle: string, types: enum, values: enum)
import { Prop, Schema, SchemaFactory } from '#nestjs/mongoose'
import { Document } from 'mongoose'
import { Types, Value } from 'src/common/enum/types.enum'
export type FeedbackQuestionDocument = FeedbackQuestion & Document
#Schema({ timestamps: true, id: true })
export class FeedbackQuestion {
#Prop()
title: string
#Prop()
subtitle: string
#Prop()
types: Types
#Prop()
value: Value
}
export const FeedbackQuestionSchema =
SchemaFactory.createForClass(FeedbackQuestion)
The feedbackQuestion schema serves as a subdocument in my feedback schema for the key question
import { Prop, Schema, SchemaFactory } from '#nestjs/mongoose'
import mongoose, { Document, ObjectId } from 'mongoose'
import { User } from './user.schema'
import { Transform, Type } from 'class-transformer'
import { FeedbackQuestion } from './feedback-question.schema'
import { distributionChannels } from 'src/common/enum/distributionChannels.enum'
export type FeedbackDocument = Feedback & Document
#Schema({ timestamps: true, id: true })
export class Feedback {
#Transform(({ value }) => value.toString())
_id: ObjectId
#Prop()
label: string
#Prop({ default: false })
status: boolean
#Prop()
question: [FeedbackQuestion]
#Prop()
comment: string
#Prop()
thankYouMessage: string
#Prop()
distributionChannels: distributionChannels
#Prop({ type: mongoose.Schema.Types.ObjectId, ref: 'User' })
#Type(() => User)
user: User
}
export const FeedbackSchema = SchemaFactory.createForClass(Feedback)
when creating my create-feedbackDto, I assigned question to be an array of type feedbackQuestion
import { Type } from 'class-transformer'
import { FeedbackQuestion } from '../../schemas/feedback-question.schema'
import { IsArray, IsEnum, IsNotEmpty, ValidateNested } from 'class-validator'
import { Types, Value } from '../enum/types.enum'
import { distributionChannels } from '../enum/distributionChannels.enum'
export class CreateFeedbackDto {
#IsNotEmpty()
label: string
status: boolean
#IsArray()
#ValidateNested({ each: true })
#Type(() => FeedbackQuestion)
question: FeedbackQuestion[]
#IsNotEmpty()
comment: string
#IsNotEmpty()
thankYouMessage: string
#IsNotEmpty()
title: string
#IsNotEmpty()
subtitle: string
#IsEnum(Types)
#IsNotEmpty()
types: Types
#IsEnum(Value)
#IsNotEmpty()
value: Value
#IsEnum(distributionChannels)
#IsNotEmpty()
distributionChannels: distributionChannels
}
In my feedback services, I want to work on questions such that I can pass in multiple objects of feedbackQuestion into the question array when creating a feedback. Please How can I do that?
The current code only takes one FeedbackQuestion object in the array
import { Injectable } from '#nestjs/common'
import { InjectModel } from '#nestjs/mongoose'
import { Model } from 'mongoose'
import { Feedback, FeedbackDocument } from '../../schemas/feedback.schema'
import {
FeedbackQuestion,
FeedbackQuestionDocument,
} from '../../schemas/feedback-question.schema'
import { IServiceResponse } from '../../common/interfaces/service.interface'
import { CreateFeedbackDto } from 'src/common/dto/create-feedback.dto'
#Inject#5406able()
export class FeedbackService {
constructor(
#Inject#5406Model(Feedback.name)
private feedbackDocumentModel: Model<FeedbackDocument>,
#Inject#5406Model(FeedbackQuestion.name)
private feedbackQuestionDocumentModel: Model<FeedbackQuestionDocument>,
) {}
async createFeedback(payload: CreateFeedbackDto): Promise<IServiceResponse> {
const feedbackQuestion = await this.feedbackQuestionDocumentModel.create({
title: payload.title,
subtitle: payload.subtitle,
type: payload.types,
value: payload.value,
})
const feedback = await this.feedbackDocumentModel.create({
label: payload.label,
status: payload.status,
question: [feedbackQuestion],
comment: payload.comment,
thankYouMesage: payload.thankYouMessage,
distributionChannels: payload.distributionChannels,
})
// feedback.question.push(feedbackQuestion)
await feedback.save()
return {
data: {
user: feedback,
},
}
}
}
This is the current response I get
"label": "Yearly Feedback",
"status": false,
"question": [
{
"title": "Yearly Feedback",
"subtitle": "Rating the Yearly performance of the organization",
"value": 1,
"_id": "627fa9b915d31bbbc0fe6908",
"createdAt": "2022-05-14T13:08:09.180Z",
"updatedAt": "2022-05-14T13:08:09.180Z",
"__v": 0
}
],
Thanks

Error: Cannot query across many-to-many for property on updating

I am try to update many to may relation.
export class CreateProductDto {
#ApiProperty()
#IsString()
description: string;
#ApiProperty()
#IsString()
name: string;
#ApiProperty({ isArray: true })
#IsNumber({}, { each: true })
#IsArray()
categoryIds: number[];
}
export class UpdateProductDto extends PartialType(CreateProductDto) {}
export class ProductsService {
constructor(
#InjectRepository(Product)
private productRepository: Repository<Product>,
private categoriesService: CategoriesService,
) {}
async update(id: number, updateProductDto: UpdateProductDto) {
let categories: Category[] = undefined;
if (updateProductDto.categoryIds) {
categories = await Promise.all(
updateProductDto.categoryIds.map(
async (id) => await this.categoriesService.findOneOrFail(id),
),
);
delete updateProductDto.categoryIds;
}
await this.productRepository.update(
{ id },
{ ...updateProductDto, categories },
);
return await this.findOneOrFail(id);
}
async findOneOrFail(id: number) {
const product = await this.productRepository.findOne({ id });
if (product) {
return product;
}
throw new BadRequestException(`Product is not present`);
}
}
#Entity()
export class Product extends BaseEntity {
#Column()
description: string;
#Column()
name: string;
#ManyToMany(() => Category, (object) => object.products, {
cascade: true,
eager: true,
})
#JoinTable()
categories: Category[];
}
#Entity()
export class Category extends BaseEntity {
#Column()
name: string;
#ManyToMany(() => Product, (object) => object.categories)
products: Product[];
}
Finally when i try to call ProductsService.update with this payload it
"categoryIds": [ 2 ]
i got an error like this
Error: Cannot query across many-to-many for property categories
Can some please help me to update many to many
In your Category Entity add the relation id of Product and use save method instead of update when you update your entity.
#Entity()
export class Category extends BaseEntity {
#Column()
name: string;
#ManyToMany(() => Product, (object) => object.categories)
products: Product[];
// Add this
#Column()
productId: string;
}
To solve problemes like i use.
async dummyUpdate(objetUpdateDto: ObjectUpdateDto): Promise<TypeReturn> {
const { idObjectToUpdate, colum1ToUpate, colum2ToUpate } = objetUpdateDto;
try {
const objectToUpdate = await this.repositoryOfEntity.findOne(idObjectToUpdate);
idObjectToUpdate.colum1ToUpate = colum1ToUpate;
idObjectToUpdate.colum2ToUpate = colum2ToUpate;
await this.repositoryOfEntity.save(objectToUpdate);
return objectToUpdate,
} catch(err) {
throw new ConflictException("your message" + err);
}
}

NestJS Mongodb Compoud Index

I am currently writing mongodb schema in nest js.
My schema is below
{
_id: {
filed1: string,
filed2: string,
field3: string,
field4: {
filed5: int
}
}
filed1: ~
...
...
Is there a way to create nestJs schema for the collection?
Is there a way to set the index for the _id field?
I've tried the following, but it didn't work.
import { DateTimeScalar } from '#/common/scalars/dateTime.scalar';
import { Field, Float, ID, Int, ObjectType } from '#nestjs/graphql';
import { Prop, raw, Schema, SchemaFactory } from '#nestjs/mongoose';
import { Document } from 'mongoose';
export type Document = MongooseClass & Document;
#ObjectType()
export class filed4 {
#Field(() => Int)
filed5: number;
}
#ObjectType()
export class compundId {
#Field(() => String)
filed1: string;
#Field(() => String)
filed2: string;
#Field(() => String)
filed3: string;
#Field(() => field4)
field4: field5;
}
#ObjectType()
#Schema({ collection: 'collection' })
export class MongooseClass {
#Field(() => ID, { nullable: false })
#Prop(
raw({
filed1: { type: String },
filed2: { type: String },
filed3: { type: string },
}),
)
_id: compundId;
filed ...
}
const MongooseSchema = SchemaFactory.createForClass(MongooseClass);
MongooseSchema.index({ _id: { filed1: 1, filed5: 1 } });
MongooseSchema.index({ filed2: 1, filed3: 1 });
MongooseSchema.index({ filed5: 1 });
export default ExcuteRateInfoMongooseSchema;
After checking the documentation, I couldn't find an answer to that question. please help me

typeorm geometry type Undefined type error

everyone. I am creating a project that uses geometry data using postgresql postgis this time. So I want to declare geometry in the column and use it, but there's an error. Could you tell me why there is an error?
Multiple official documents were checked, but no method was found.
Commenting the coordinate column will create the code normally.
import {
Column,
CreateDateColumn,
Entity,
JoinColumn,
ManyToOne,
PrimaryGeneratedColumn
} from 'typeorm';
import { Location_Group } from './location_group.entity';
import { Geometry } from 'geojson';
import { Field, ID, Int, ObjectType } from '#nestjs/graphql';
#ObjectType()
#Entity()
export class Location {
#Field(() => ID)
#PrimaryGeneratedColumn('increment')
id: number;
#Field(() => String)
#Column({ type: 'varchar' })
name: string;
#Field()
#Column({
type: 'geometry',
nullable: true,
spatialFeatureType: 'Point',
srid: 4326
})
coordinate: Geometry;
#Field(() => Int)
#Column({ type: 'int' })
order_number: number;
#Field()
#CreateDateColumn({ type: 'timestamptz' })
created_at: Date;
#Field(() => Location_Group)
#ManyToOne(
() => Location_Group,
(location_group) => location_group.location
)
#JoinColumn([{ name: 'location_group_id', referencedColumnName: 'id' }])
location_group: Location_Group;
}
There is someone who wants me to share the scalar I made, so I write it here. I hope this code helps you.
import { GraphQLScalarType } from 'graphql';
export const GeoJSONPoint = new GraphQLScalarType({
name: 'GeoJSONPoint',
description: 'Geometry scalar type',
parseValue(value) {
return value;
},
serialize(value) {
return value;
},
parseLiteral(ast) {
const geometryData = {
type: '',
coordinates: []
};
for (const i in ast['fields']) {
if (ast['fields'][i]['name']['value'] == 'type') {
if (ast['fields'][i]['value']['value'] != 'point') {
return null;
}
geometryData.type = ast['fields'][i]['value']['value'];
}
if (ast['fields'][i]['name']['value'] == 'coordinate') {
for (const j in ast['fields'][i]['value']['values']) {
geometryData.coordinates.push(
parseFloat(
ast['fields'][i]['value']['values'][j]['value']
)
);
}
}
}
return geometryData;
}
});