Prisma Nodejs, relation with ids to get the name - mysql

im in trouble to find a way to make this, i want in "serieName" the name of the serie, but always return de id, i dont know what i need to do to make this relation correct, im trying to find a solution, but nothing works.
this is my models:
in Series model, i have a name, and in Figures_table i made a relation with him, and i want to get only the name when i pass the id for the field, so if Series have id: 1, name: "something", i want to show "something" not the id, but only show id.
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model Series {
id Int #unique #default(autoincrement())
serie String
Figures_table Figures_table[]
}
model Manufacturers {
id String #unique
manufacturer String
Figures_table Figures_table[]
}
model Figures_table {
id String #unique
name String #db.LongText
category String #db.LongText
price String #db.LongText
specifications String #db.LongText
releaseInfo String #db.LongText
details String #db.LongText
serieName Int
manufacturerName String #db.VarChar(191)
createdAt DateTime #default(now())
manufacturer Manufacturers #relation(fields: [manufacturerName], references: [id])
series Series #relation(fields: [serieName], references: [id])
Images Images[]
}
model Images {
id Int #unique #default(autoincrement())
link String
figureID String
figureReferenceID Figures_table #relation(fields: [figureID], references: [id])
}

Here's a script which would include the name of the Series while fetching a record from the figures_table
import { PrismaClient, Prisma } from '#prisma/client';
const prisma = new PrismaClient({
log: ['query', 'info', 'warn'],
});
async function main() {
await prisma.figures_table.create({
data: {
category: 'Figures Table Category',
details: 'Figures Table Details',
name: 'Figures Table Name',
id: '1',
price: '1',
releaseInfo: 'Figures Table Release Info',
specifications: 'Figures Table Specifications',
series: {
create: {
serie: 'Series 1',
},
},
manufacturer: {
create: {
manufacturer: 'Manufacturer 1',
id: '1',
},
},
},
});
const figures_table = await prisma.figures_table.findUnique({
where: {
id: '1',
},
include: {
series: true,
},
});
console.log(figures_table);
}
main()
.catch((e) => {
throw e;
})
.finally(async () => {
await prisma.$disconnect();
});
We used the include section to get the details of Series relation.
Response:
{
id: '1',
name: 'Figures Table Name',
category: 'Figures Table Category',
price: '1',
specifications: 'Figures Table Specifications',
releaseInfo: 'Figures Table Release Info',
details: 'Figures Table Details',
serieName: 1,
manufacturerName: '1',
createdAt: 2022-10-11T12:33:37.768Z,
series: { id: 1, serie: 'Series 1' }
}

Related

Prisma Many-to-Many relations with findMany (select)

I am facing an error with Prisma, it does not recognize my request which seems quite simple to me. I need to use "select" to retrieve only certain fields from the table.
Post model:
model Post {
id String #id #default(cuid())
title String
createdAt DateTime? #default(now())
categories CategoriesOnPosts[]
keywords KeywordsOnPosts[]
##map("posts")
}
Category model:
model Category {
id String #id #default(cuid())
name String
createdAt DateTime? #default(now())
posts CategoriesOnPosts[]
##map("categories")
}
CategoriesOnPosts model:
model CategoriesOnPosts {
postId String
categoryId String
post Post #relation(fields: [postId], references: [id])
category Category #relation(fields: [categoryId], references: [id])
##id([postId, categoryId])
##map("categoriesPosts")
}
My Prisma query:
export const getPosts = async () =>
await prisma.post.findMany({
select: {
id: true,
title: true,
categories: {
select: {
name: true,
slug: true,
},
},
createdAt: true,
},
orderBy: [
{
createdAt: 'desc',
},
],
});
I get the following error and I don't know how to fix it.
Unknown field categories for select statement on model Post.
Available options are listed in green.

Using explicit Many to Many Relation in Prisma

I have the following User and Group models that share a many-to-many relation:
model User {
id String #id #default(uuid())
email String #unique
groups UsersGroups[]
##map("user")
}
model Group {
id String #id #default(uuid())
name String
users UsersGroups[]
##map("group")
}
model UsersGroups {
user User #relation(fields: [userId], references: [id])
userId String #map(name: "user_id")
group Group #relation(fields: [groupId], references: [id])
groupId String #map(name: "group_id")
##id([userId, groupId])
##map("users_groups")
}
I'm having trouble using the connect API in Prisma to connect the users and groups. Here's what I have:
await prisma.group.update({
where: {
id: groupId,
},
data: {
users: {
connect: users.map((user) => ({ id: user.id })),
},
},
include: { users: true },
});
That doesn't work and here is the error I'm getting in the console:
PrismaClientValidationError:
Invalid `prisma.group.update()` invocation:
{
where: {
id: '64ce24c7-3054-42f2-b49f-4cdb52cf1bc7'
},
data: {
users: {
connect: [
{
id: '0b3f4a51-0efe-4b0a-8763-e71bc8091b86'
~~
}
]
}
},
include: {
users: true
}
}
Unknown arg `id` in data.users.connect.0.id for type UsersGroupsWhereUniqueInput. Available args:
type UsersGroupsWhereUniqueInput {
userId_groupId?: UsersGroupsUserIdGroupIdCompoundUniqueInput
}
From that above, it looks as though it's attempting to connect a user with id: '0b3f4a51-0efe-4b0a-8763-e71bc8091b86' (which is a user that exists) to the group with id: '64ce24c7-3054-42f2-b49f-4cdb52cf1bc7' (which also exists).
I'd be very grateful if someone could point out where I'm going wrong as I've been going in circles with this for a while now...
You are using an explicit many-to-many relation, cf. https://www.prisma.io/docs/concepts/components/prisma-schema/relations/many-to-many-relations#explicit-many-to-many-relations
I.e. you have defined the model UsersGroups yourself.
As a consequence, you would have to manage/create the records in this table yourself and connect it with the entry in the third table, e.g. like this (haven't tested it):
prisma.group.update({
where: {
id: groupId,
},
data: {
users: { create: { user: { connect: { id: userId } } } },
},
include: { users: true },
});
or if you want to loop over an list:
prisma.group.update({
where: {
id: groupId,
},
data: {
users: {
create: users.map((user) => ({
user: { connect: { id: user.id } },
})),
},
},
include: { users: true },
});
I would suggest to replace groups UsersGroups[] and users UserGroups[] with
userGroups UsersGroups[] in the schema to make it clearer.
As an alternative to explicit relationships you could try to use implicit many-to-many relations in the schema like this:
model User {
id String #id #default(uuid())
email String #unique
groups Group[]
##map("user")
}
model Group {
id String #id #default(uuid())
name String
users User[]
##map("group")
}
cf. https://www.prisma.io/docs/concepts/components/prisma-schema/relations/many-to-many-relations#implicit-many-to-many-relations

Prisma - Unique constraint failed, while there is no unique field in schema

I am using prisma with three models,
model User {
id String #id #default(cuid())
name String #unique #db.VarChar(35)
email String #unique #db.VarChar(512)
password String #db.VarChar(1024)
details String #default("") #db.VarChar(512)
avatar String #default("/default-avatar.svg") #db.VarChar(150)
activity String #default("Online") #db.VarChar(25)
likes Int #default(0)
suggestions Boolean #default(false)
verified Boolean #default(false)
blockedUsers BlockedUser[]
comments Comment[]
communities Community[]
communityMembers CommunityMember[]
followers Follower[]
friends Friend[]
messages Message[]
posts Post[]
openDMs DM[]
interests UserInterest[]
##map("user")
}
model Community {
id String #id #default(cuid())
title String #unique #db.VarChar(35)
details String #db.VarChar(512)
memberID String?
membersUser User[]
members CommunityMember[]
interests CommunityInterest[]
posts Post[]
##map("community")
}
model CommunityMember {
id String #id #default(cuid())
nickname String?
userID String
communityID String
user User #relation(fields: [userID], references: [id])
community Community #relation(fields: [communityID], references: [id])
owner Boolean
##map("community_member")
}
I have a route in my backend that causes the problem. It creates a new community member table with prisma client and connects the existing user and community to itself, with their ids.
When I do this, I get an error: Unique constraint failed on the constraint: community_member_communityID_key
Here is the code with the creation of the community member:
await prisma.communityMember.create({
data: {
nickname: response.account.name,
user: {
connect: { id: response.account.id }
},
community: {
connect: { id: communityID }
},
owner: false
}
});
I have tried dropping the database and resetting the prisma migrations, with no luck.
When I view the table in mysql, it is apparent that the communityID and userID fields are set as unique, so I think this problem has to do with prisma migrate.
Does anybody know what's happening, and how I can successfully create these fields without them being unique?
Why are you using connect? According to documentation
https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#nested-writes
In nested writes you should use create:
await prisma.communityMember.create({
data: {
nickname: response.account.name,
user: {
create: [
{id: response.account.id}
]
},
community: {
create: [
{id: communityID}
]
},
owner: false
}
})

TypeORM save nested objects

I'm working on a express (with TypeORM) + ReactJS app.
The problem is that I have 3 entities linked by OneToMany relationship like this:
customer
product(linked to customer)
model(linked to product)
import { Product } from './product.entity'
#Entity('customer')
export class Customer extends BaseEntity{
#PrimaryGeneratedColumn()
readonly id: number;
#Column ({name: 'name'})
name : string;
#Column ({name: 'test', nullable: true})
test : string;
#OneToMany(() => Product, product => product.customer)
// #JoinColumn({ name: 'product_id' })
products: Product[]
}
import {Customer} from './customer.entity'
import {Model} from './model.entity'
#Entity('product')
export class Product extends BaseEntity{
#PrimaryGeneratedColumn()
readonly id: number;
#Column ({name: 'name'})
name : string;
#Column ({name: 'test', nullable: true})
test : string;
#Column ({name: 'deleted', nullable: true})
deleted : string;
#ManyToOne(() => Customer, customer => customer.products)
#JoinColumn({ name: 'customer_id' })
customer: Customer;
#OneToMany(() => Model, model => model.product)
#JoinColumn({ name: 'customer_id' })
models: Model[]
}
import { Product } from "./product.entity";
#Entity('model')
export class Model extends BaseEntity{
#PrimaryGeneratedColumn()
readonly id: number;
#Column ({name: 'name'})
name : string;
#Column ({name: 'size', nullable: true})
size : string;
#Column ({name: 'deleted', nullable: true})
deleted : string;
#ManyToOne(() => Product, product => product.models)
#JoinColumn({ name: 'product_id' })
product: Product;
}
The save method from Express is:
static add = async(req: Request, res)=> {
const connection = getConnection();
const queryRunner = connection.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
let customer: Customer
customer = await queryRunner.manager.getRepository(Customer).findOneOrFail(req.body.id)
const productsReq: Array<Product> = req.body.products
productsReq.forEach(async (product: any) => {
let updatedProd = {...product, customer: customer}
const savedProd = await queryRunner.manager.getRepository(Product).save({...updatedProd})
product.models.forEach(async (model: any) => {
let updatedModel = {...model, product: savedProd}
await queryRunner.manager.getRepository(Model).save(updatedModel)
});
});
await queryRunner.commitTransaction();
return res.send('Saving done')
} catch (error) {
console.log(error)
await queryRunner.rollbackTransaction();
res.status(500).send('Some error occurs');
} finally {
}
}
Currently, in the DB, I have the following data:
1 customer with id 30
name
id
test
first customer
30
test column
1 product with id 119 linked to customer 30
id
name
test
customer_id
deleted
119
first product
test column
30
2 models with ids: 90 and 91 linked to product 119
id
name
size
deleted
product_id
91
second model witout id
2000
119
90
first model with id
1000
119
Next, from React i'm trying to update only the model with id 90 and add a new model.
(So i'm not sending to backend all the models, model with id 91 is not sent).
The JSON object sent from frontend to backend looks like this:
{
"id": 30,
"name": "first customer",
"test": "test column",
"products": [
{
"id" : 119,
"name": "first product",
"test": "test column",
"models": [
{
"id": 90,
"name": "first model with id",
"size": 1000
},
{
"name": "second model witout id",
"size": 2000
}
]
}
]
}
But the problem is in DB the foreing key "product_id" on table "model" is set to null for model with id 91 and a new row(92) is inserted.
The result is:
|id|name|size|deleted|product_id|
|--|----|----|-------|----------|
|91|second model witout id|2000|||
|90|first model with id|1000||119|
|92|second model witout id|2000||119|
How can I add a new model and update an existing one without sending all the existing models in DB ?
I think i found a solutions.
I changed the save method from Express like this:
static add = async(req: Request, res)=> {
const connection = getConnection();
const queryRunner = connection.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
let customer: Customer
let customerReq: any = req.body
customer = await queryRunner.manager.getRepository(Customer).findOneOrFail(req.body.id)
const productsReq: Array<Product> = req.body.products
productsReq.forEach(async (product: any) => {
let updatedProd = {...product, customer: customer}
let addedModels: Model[] = []
product.models.forEach(async (model: any) => {
const updatedModel = await queryRunner.manager.getRepository(Model).save({...model, product: product})
addedModels.push(updatedModel)
});
const existingProd = await queryRunner.manager.getRepository(Product).save({...updatedProd})
await (await existingProd.models).push(...addedModels)
const savedProd = await queryRunner.manager.getRepository(Product).save({...updatedProd})
});
await queryRunner.commitTransaction();
return res.send('Adding ok')
} catch (error) {
console.log(error)
await queryRunner.rollbackTransaction();
res.status(500).send('Something went terribly wrong');
} finally {
console.log('release')
// await queryRunner.release();
}
}
It's strange becouse 2 transaction are started:
query: START TRANSACTION
query: SELECT "Customer"."id" AS "Customer_id", "Customer"."name" AS "Customer_name", "Customer"."test" AS "Customer_test" FROM "customer" "Customer" WHERE "Customer"."id" IN ($1) -- PARAMETERS: [30]
query: SELECT "Customer"."id" AS "Customer_id", "Customer"."name" AS "Customer_name", "Customer"."test" AS "Customer_test" FROM "customer" "Customer" WHERE "Customer"."id" IN ($1) -- PARAMETERS: [30]
query: COMMIT
query: SELECT "Model"."id" AS "Model_id", "Model"."name" AS "Model_name", "Model"."size" AS "Model_size", "Model"."deleted" AS "Model_deleted", "Model"."product_id" AS "Model_product_id" FROM "model" "Model" WHERE "Model"."id" IN ($1) -- PARAMETERS: [132]
query: SELECT "Product"."id" AS "Product_id", "Product"."name" AS "Product_name", "Product"."test" AS "Product_test", "Product"."deleted" AS "Product_deleted", "Product"."customer_id" AS "Product_customer_id" FROM "product" "Product" WHERE "Product"."id" IN ($1) -- PARAMETERS: [119]
query: INSERT INTO "model"("name", "size", "deleted", "product_id") VALUES ($1, $2, DEFAULT, $3) RETURNING "id" -- PARAMETERS: ["second model witout id",2000,119]
release
Morgan --> POST 200 /test # Tue, 04 May 2021 14:28:08 GMT ::ffff:127.0.0.1 from undefined PostmanRuntime/7.28.0
query: START TRANSACTION
query: SELECT "Product"."id" AS "Product_id", "Product"."name" AS "Product_name", "Product"."test" AS "Product_test", "Product"."deleted" AS "Product_deleted", "Product"."customer_id" AS "Product_customer_id" FROM "product" "Product" WHERE "Product"."id" IN ($1) -- PARAMETERS: [119]
query: UPDATE "model" SET "size" = $2 WHERE "id" IN ($1) -- PARAMETERS: [132,8000]
query: COMMIT

How to Print instance in Flutter/Dart? [duplicate]

This question already has answers here:
Default stringify for objects, equivalent to Java's toString?
(3 answers)
Closed 1 year ago.
I have one data type Map<String,CartItem> _items = {};
And using print(_items)
And the output is:
{
p1: Instance of 'CartItem',
p2: Instance of 'CartItem'
}
Is there any method by which I can see the full logs(values) of CartItem? as my expectation is:
{
p1: some json formatted structure,
p2: some json formatted structure
}
class CartItem {
final String id;
final String title;
CartItem({
#required this.id,
#required this.title,
});
}
You just need to override your toString method:
class CartItem {
final String id;
final String title;
CartItem({
required this.id,
required this.title,
});
#override
String toString() {
return '{id: $id, title: $title}';
}
}
Usage:
main() async {
CartItem item = CartItem(id: '1', title: 'title');
print(item); // {id: 1, title: title}
Map<String, CartItem> items = {
'p1': CartItem(id: '1', title: 'title'),
'p2': CartItem(id: '2', title: 'titl2'),
};
print(items); // {p1: {id: 1, title: title}, p2: {id: 2, title: titl2}}
List<CartItem> list = [
CartItem(id: '1', title: 'title'),
CartItem(id: '2', title: 'title2'),
];
print(list); // [{id: 1, title: title}, {id: 2, title: title2}]
}
You have to loop through the items to get their specific values and not their instances.
_items.forEach((item) {
print('id: ${item.id}, title: ${item.title}');
});