So I have this query:
START TRANSACTION;
CREATE TABLE `users` (
`id` int PRIMARY KEY NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`registration_date` timestamp NOT NULL,
`address` varchar(255),
`description` varchar(1000),
`studio` varchar(255),
`email` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
`is_looking_for_work` boolean,
`last_active` timestamp,
`last_login` timestamp,
`profile_photo` varchar(2000)
);
CREATE TABLE `availability` (
`id` int PRIMARY KEY NOT NULL AUTO_INCREMENT,
`start_time` timestamp NOT NULL,
`end_time` timestamp NOT NULL,
`description` varchar(500),
`user_id` int NOT NULL
);
CREATE TABLE `chats` (
`id` int PRIMARY KEY NOT NULL AUTO_INCREMENT,
`initiator_id` int NOT NULL,
`invited_id` int NOT NULL
);
CREATE TABLE `messages` (
`id` int PRIMARY KEY NOT NULL AUTO_INCREMENT,
`chat_id` int NOT NULL,
`author_id` int NOT NULL,
`content` varchar(1000) NOT NULL,
`creation_date` timestamp NOT NULL
);
CREATE TABLE `offers` (
`id` int PRIMARY KEY NOT NULL AUTO_INCREMENT,
`author_id` int,
`colors` ENUM ('white', 'red'),
`project_image` varchar(10000),
`finished_image` varchar(10000),
`price` int NOT NULL,
`description` varchar(500),
`time_needed` int NOT NULL,
`is_available` boolean NOT NULL,
`is_in_portfolio` boolean
);
CREATE TABLE `meetings` (
`id` int PRIMARY KEY NOT NULL AUTO_INCREMENT,
`provider` int NOT NULL,
`client` int NOT NULL,
`date` timestamp NOT NULL,
`duration` int NOT NULL,
`description` varchar(1000) NOT NULL,
`offer_id` int NOT NULL
);
CREATE TABLE `tags` (
`id` int PRIMARY KEY NOT NULL AUTO_INCREMENT,
`tag` varchar(255) NOT NULL,
`description` varchar(1000),
`is_style` boolean NOT NULL
);
CREATE TABLE `tags_to_offers` (
`id` int PRIMARY KEY NOT NULL AUTO_INCREMENT,
`offer_id` int NOT NULL,
`tag_id` int NOT NULL
);
CREATE TABLE `tags_to_users` (
`id` int PRIMARY KEY NOT NULL AUTO_INCREMENT,
`user_id` int NOT NULL,
`tag_id` int NOT NULL
);
ALTER TABLE `offers` ADD FOREIGN KEY (`author_id`) REFERENCES `users` (`id`);
ALTER TABLE `availability` ADD FOREIGN KEY (`user_id`) REFERENCES `users` (`id`);
ALTER TABLE `chats` ADD FOREIGN KEY (`initiator_id`) REFERENCES `users` (`id`);
ALTER TABLE `chats` ADD FOREIGN KEY (`invited_id`) REFERENCES `users` (`id`);
ALTER TABLE `messages` ADD FOREIGN KEY (`chat_id`) REFERENCES `chats` (`id`);
ALTER TABLE `messages` ADD FOREIGN KEY (`author_id`) REFERENCES `users` (`id`);
ALTER TABLE `tags_to_offers` ADD FOREIGN KEY (`offer_id`) REFERENCES `offers` (`id`);
ALTER TABLE `tags_to_offers` ADD FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`);
ALTER TABLE `tags_to_users` ADD FOREIGN KEY (`user_id`) REFERENCES `users` (`id`);
ALTER TABLE `tags_to_users` ADD FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`);
ALTER TABLE `meetings` ADD FOREIGN KEY (`provider`) REFERENCES `users` (`id`);
ALTER TABLE `meetings` ADD FOREIGN KEY (`client`) REFERENCES `users` (`id`);
ALTER TABLE `meetings` ADD FOREIGN KEY (`offer_id`) REFERENCES `offers` (`id`);
COMMIT;
It causes prisma to create this schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model availability {
id Int #id #default(autoincrement())
start_time DateTime
end_time DateTime
description String?
user_id Int
users users #relation(fields: [user_id], references: [id])
##index([user_id], name: "user_id")
}
model chats {
id Int #id #default(autoincrement())
initiator_id Int
invited_id Int
users_chats_initiator_idTousers users #relation("chats_initiator_idTousers", fields: [initiator_id], references: [id])
users_chats_invited_idTousers users #relation("chats_invited_idTousers", fields: [invited_id], references: [id])
messages messages[]
##index([initiator_id], name: "initiator_id")
##index([invited_id], name: "invited_id")
}
model meetings {
id Int #id #default(autoincrement())
provider Int
client Int
date DateTime
duration Int
description String
offer_id Int
users_meetings_clientTousers users #relation("meetings_clientTousers", fields: [client], references: [id])
offers offers #relation(fields: [offer_id], references: [id])
users_meetings_providerTousers users #relation("meetings_providerTousers", fields: [provider], references: [id])
##index([client], name: "client")
##index([offer_id], name: "offer_id")
##index([provider], name: "provider")
}
model messages {
id Int #id #default(autoincrement())
chat_id Int
author_id Int
content String
creation_date DateTime
users users #relation(fields: [author_id], references: [id])
chats chats #relation(fields: [chat_id], references: [id])
##index([author_id], name: "author_id")
##index([chat_id], name: "chat_id")
}
model offers {
id Int #id #default(autoincrement())
author_id Int?
colors offers_colors?
project_image String?
finished_image String?
price Int
description String?
time_needed Int
is_available Boolean
is_in_portfolio Boolean?
users users? #relation(fields: [author_id], references: [id])
meetings meetings[]
tags_to_offers tags_to_offers[]
##index([author_id], name: "author_id")
}
model tags {
id Int #id #default(autoincrement())
tag String
description String?
is_style Boolean
tags_to_offers tags_to_offers[]
tags_to_users tags_to_users[]
}
model tags_to_offers {
id Int #id #default(autoincrement())
offer_id Int
tag_id Int
offers offers #relation(fields: [offer_id], references: [id])
tags tags #relation(fields: [tag_id], references: [id])
##index([offer_id], name: "offer_id")
##index([tag_id], name: "tag_id")
}
model tags_to_users {
id Int #id #default(autoincrement())
user_id Int
tag_id Int
tags tags #relation(fields: [tag_id], references: [id])
users users #relation(fields: [user_id], references: [id])
##index([tag_id], name: "tag_id")
##index([user_id], name: "user_id")
}
model users {
id Int #id #default(autoincrement())
name String
registration_date DateTime
address String?
description String?
studio String?
email String
password String
is_looking_for_work Boolean?
last_active DateTime?
last_login DateTime?
profile_photo String?
availability availability[]
chats_chats_initiator_idTousers chats[] #relation("chats_initiator_idTousers")
chats_chats_invited_idTousers chats[] #relation("chats_invited_idTousers")
meetings_meetings_clientTousers meetings[] #relation("meetings_clientTousers")
meetings_meetings_providerTousers meetings[] #relation("meetings_providerTousers")
messages messages[]
offers offers[]
tags_to_users tags_to_users[]
}
enum offers_colors {
white
red
}
Which, is not what I was going for. I wanted something like this (GraphQL types):
type User {
id: Int!
name: String!
registration_date: String!
address: String
description: String
studio: String
email: String!
password: String!
is_looking_for_work: Boolean
last_active: String
last_login: String
profile_photo: String
availability: [Availability]
chats: [Chat]
meetings: [Meeting]
tags: [Tag]
}
type Offer {
id: Int!
author_id: Int!
colors: String
project_image: String!
finished_image: String
price: Int!
description: String
time_needed: Int!
is_available: Boolean!
is_in_portfolio: Boolean
tags: [Tag]
}
type Availability {
id: Int!
start_time: String!
end_time: String!
description: String
user_id: Int!
}
type Chat {
id: Int!
initiator_id: Int!
invited_id: Int!
messages: [Message]
}
type Message {
id: Int!
chat_id: Int!
author_id: Int!
content: Int!
creation_date: Int!
}
type Meeting {
id: Int!
providerId: Int!
clientId: Int!
date: String!
duration: Int!
description: String!
offer_id: Int!
}
type Tag {
id: Int!
tag: String!
description: String
is_style: Boolean!
}
For example let's look at user for simplicity:
SQL
CREATE TABLE `users` (
`id` int PRIMARY KEY NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`registration_date` timestamp NOT NULL,
`address` varchar(255),
`description` varchar(1000),
`studio` varchar(255),
`email` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
`is_looking_for_work` boolean,
`last_active` timestamp,
`last_login` timestamp,
`profile_photo` varchar(2000)
);
Prisma
model users {
id Int #id #default(autoincrement())
name String
registration_date DateTime
address String?
description String?
studio String?
email String
password String
is_looking_for_work Boolean?
last_active DateTime?
last_login DateTime?
profile_photo String?
availability availability[]
chats_chats_initiator_idTousers chats[] #relation("chats_initiator_idTousers")
chats_chats_invited_idTousers chats[] #relation("chats_invited_idTousers")
meetings_meetings_clientTousers meetings[] #relation("meetings_clientTousers")
meetings_meetings_providerTousers meetings[] #relation("meetings_providerTousers")
// the 4 above: Why are they not in objects?
messages messages[]
offers offers[]
tags_to_users tags_to_users[]
}
What I was hoping for
type User {
id: Int!
name: String!
registration_date: String!
address: String
description: String
studio: String
email: String!
password: String!
is_looking_for_work: Boolean
last_active: String
last_login: String
profile_photo: String
availability: [Availability]
chats: [Chat]
meetings: [Meeting]
// meeting and chats. Why are they not like this?
tags: [Tag]
}
And as you can see
chats_chats_initiator_idTousers chats[] #relation("chats_initiator_idTousers")
chats_chats_invited_idTousers chats[] #relation("chats_invited_idTousers")
meetings_meetings_clientTousers meetings[] #relation("meetings_clientTousers")
meetings_meetings_providerTousers meetings[] #relation("meetings_providerTousers")
This is how prisma made the chats and meethings. Also it added objects. But why did it add the 4 above?
What did I mess up in my schema? Or can I create a db schema from my graphql types?
Related
I have an existing table in MySQL database named "users" ("login", "password") with existing columns.
When I try to create a migration using the command "migration:generate" TypeORM generates the migration and drops all columns and creates it like this again:
Users table DDL
create table if not exists users
(
id int auto_increment primary key,
login varchar(50) not null,
name varchar(255) not null,
surname varchar(50) null,
patronymic varchar(255) null,
mail varchar(255) not null,
phone varchar(255) null,
password varchar(255) not null,
);
Migration
await queryRunner.query(`ALTER TABLE \`users\` DROP COLUMN \`login\``);
await queryRunner.query(`ALTER TABLE \`users\` DROP COLUMN \`password\``);
await queryRunner.query(`ALTER TABLE \`users\` ADD \`login\` varchar(50) NOT NULL`);
await queryRunner.query(`ALTER TABLE \`users\` ADD \`password\` varchar(255) NOT NULL`);
...
Entity
#Entity({
name: 'users',
})
export class UserModel {
#PrimaryGeneratedColumn()
id: TUserID;
#Column({ length: 50, nullable: true })
login: string;
#Column()
name: string;
#Column({ length: 50, nullable: true })
surname: string;
#Column({ length: 50, nullable: true })
patronymic: string;
#Column({ length: 50 })
mail: string;
#Column()
password: string;
}
How can I fix this problem? I need to create an entity so that new migrations can be generated without deleting columns
i'm currently working on a twitter clone with express / prisma / postgreSQL for my backend.
I'm struggling to imitate twitter's feed.
Here's my current prisma Schema
model User {
id String #id #default(cuid())
email String #unique
username String #unique
profilename String?
password String
bio String?
image String?
createdAt DateTime #default(now())
isAdmin Boolean #default(false)
tweets Tweet[]
retweets Retweet[]
likes Like[]
followers Follows[] #relation("follower")
following Follows[] #relation("following")
}
model Follows {
follower User #relation("following", fields: [followerId], references: [id])
followerId String
following User #relation("follower", fields: [followingId], references: [id])
followingId String
createdAt DateTime #default(now())
##id([followerId, followingId])
}
model Tweet {
id String #id #default(cuid())
content String
createdAt DateTime #default(now())
deleted Boolean #default(false)
media String[]
author User #relation(fields: [authorId], references: [id], onDelete: Cascade)
authorId String
originalTweet Tweet? #relation("replies", fields: [originalTweetId], references: [id], onDelete: Cascade)
originalTweetId String?
responses Tweet[] #relation("replies")
likes Like[]
retweets Retweet[]
hashtags Hashtag[]
}
model Hashtag {
id String #id #default(cuid())
name String #unique
createdAt DateTime #default(now())
tweets Tweet[]
}
model Retweet {
id String #id #default(cuid())
tweet Tweet #relation(fields: [tweetId], references: [id], onDelete: Cascade)
tweetId String
user User #relation(fields: [userId], references: [id], onDelete: Cascade)
userId String
createdAt DateTime #default(now())
}
model Like {
id String #id #default(cuid())
tweet Tweet #relation(fields: [tweetId], references: [id], onDelete: Cascade)
tweetId String
user User #relation(fields: [userId], references: [id], onDelete: Cascade)
userId String
createdAt DateTime #default(now())
}
and my current function to get user feed
exports.getUserFeed = async (userId, options = {}) => {
try {
const user = await prisma.user.findUnique({
where: { id: userId },
include: { following: true },
})
if (user.following.length === 0) {
return prisma.tweet.findMany({
orderBy: {
createdAt: "desc",
},
...options,
})
}
return prisma.tweet.findMany({
where: {
OR: [
{
author: {
followers: {
some: {
followerId: userId,
},
},
},
},
{
likes: {
some: {
user: {
followers: {
some: {
followerId: userId,
},
},
},
},
},
},
{
retweets: {
some: {
user: {
followers: {
some: {
followerId: userId,
},
},
},
},
},
},
],
},
orderBy: {
createdAt: "desc",
},
...options,
})
} catch (err) {
throw new Error(err)
}
}
With this i get tweets posted by user i follow, liked by user i follow and retweeted by user i follow but order by tweet's created at not by the "event" created at.
To solve this i thought about creating a new model called Event or Status with optionnal feed like:
isRetweet ?
isLike ?
etc
and then retrieve this instead of tweet model.
But it seems messy and complex for no reason.
Is there a way to actually define a better schema or do a better query ?
Thanks a lot.
I want to find only one post matching by post id and prodCode
below is my query code. It doesn't work.
If i change findUnique to findFirst. it works.
const post = await client.post.findUnique({
where: {
AND: [
{ id: postId },
{
product: {
prodCode,
},
},
],
},
});
prisma model
model Product {
id Int #id #default(autoincrement())
prodName String
prodCode String #unique
posts Post[]
holdings Holding[]
proposes Propose[]
}
model Post {
id Int #id #default(autoincrement())
user User #relation(fields: [userId], references: [id])
userId Int
product Product #relation(fields: [productId], references: [id])
productId Int
title String
content String
createdAt DateTime #default(now())
}
Since Post.id is unique, you don't need to filter by prodCode as well. You could just query the post record with the needed id and then check if the connected product has the right prodCode.
I would just do this:
const post = await prisma.post.findUnique({
where: {
id: postId
},
include: {
product: true
}
});
if (post.product.prodCode === prodCode) {
// No result for desired query
} else {
// "post" variable contains result of desired query
}
I am wondering if it is possible to pass multiple IDs to a useQuery for apollo hook. Or run a single query per ID, and if so how would I go about doing so.
I have the following query
const DECOR_SHEET = gql`
query GetDecorSheet($id: ID!) {
findDecorSheetByID(id:$id){
refIdArray
sheetName
_id
}
}
`;
and the following useQuery hook
const { loading, error, data: sheetData } = useQuery(DECOR_SHEET, {
variables: { id: id },
context: {
headers: {
authorization: cookieBearer,
},
},
});
I have the following IDs 293164663883956749, 293526016787218952 and I would like to return into one object in order to render into a component.
I am using Fauna DB and this is the input graphQL schema
type Catalog {
decor: Boolean
clothing: Boolean
supplies: Boolean
furniture: Boolean
owner: User
}
type Decor {
description: String
pieces: Int
purchaser: String
alterations: Boolean
cost: Int
purchaseDate: Date
category: String
image: String
itemNum: Int
owner: User!
visible: Boolean
}
type DecorSheet {
sheetName: String
refIdArray: String
owner: User!
}
type User {
email: String! #unique
catalog: Catalog
decor: [Decor!] #relation
decorSheet: [DecorSheet!] #relation
}
and this is the generated schema
directive #embedded on OBJECT
directive #collection(name: String!) on OBJECT
directive #index(name: String!) on FIELD_DEFINITION
directive #resolver(
name: String
paginated: Boolean! = false
) on FIELD_DEFINITION
directive #relation(name: String) on FIELD_DEFINITION
directive #unique(index: String) on FIELD_DEFINITION
type Catalog {
_id: ID!
decor: Boolean
clothing: Boolean
supplies: Boolean
owner: User
furniture: Boolean
_ts: Long!
}
input CatalogInput {
decor: Boolean
clothing: Boolean
supplies: Boolean
furniture: Boolean
owner: CatalogOwnerRelation
}
input CatalogOwnerRelation {
create: UserInput
connect: ID
disconnect: Boolean
}
scalar Date
type Decor {
purchaseDate: Date
visible: Boolean
image: String
description: String
_id: ID!
alterations: Boolean
cost: Int
pieces: Int
category: String
owner: User!
purchaser: String
itemNum: Int
_ts: Long!
}
input DecorInput {
description: String
pieces: Int
purchaser: String
alterations: Boolean
cost: Int
purchaseDate: Date
category: String
image: String
itemNum: Int
owner: DecorOwnerRelation
visible: Boolean
}
input DecorOwnerRelation {
create: UserInput
connect: ID
}
type DecorPage {
data: [Decor]!
after: String
before: String
}
type DecorSheet {
refIdArray: String
_id: ID!
sheetName: String
owner: User!
_ts: Long!
}
input DecorSheetInput {
sheetName: String
refIdArray: String
owner: DecorSheetOwnerRelation
}
input DecorSheetOwnerRelation {
create: UserInput
connect: ID
}
type DecorSheetPage {
data: [DecorSheet]!
after: String
before: String
}
scalar Long
type Mutation {
updateUser(
id: ID!
data: UserInput!
): User
createUser(data: UserInput!): User!
createDecorSheet(data: DecorSheetInput!): DecorSheet!
createDecor(data: DecorInput!): Decor!
deleteCatalog(id: ID!): Catalog
updateCatalog(
id: ID!
data: CatalogInput!
): Catalog
updateDecor(
id: ID!
data: DecorInput!
): Decor
updateDecorSheet(
id: ID!
data: DecorSheetInput!
): DecorSheet
deleteDecor(id: ID!): Decor
deleteUser(id: ID!): User
createCatalog(data: CatalogInput!): Catalog!
deleteDecorSheet(id: ID!): DecorSheet
}
type Query {
findUserByID(id: ID!): User
findCatalogByID(id: ID!): Catalog
findDecorByID(id: ID!): Decor
findDecorSheetByID(id: ID!): DecorSheet
}
scalar Time
type User {
catalog: Catalog
email: String!
_id: ID!
decor(
_size: Int
_cursor: String
): DecorPage!
decorSheet(
_size: Int
_cursor: String
): DecorSheetPage!
_ts: Long!
}
input UserCatalogRelation {
create: CatalogInput
connect: ID
disconnect: Boolean
}
input UserDecorRelation {
create: [DecorInput]
connect: [ID]
disconnect: [ID]
}
input UserDecorSheetRelation {
create: [DecorSheetInput]
connect: [ID]
disconnect: [ID]
}
input UserInput {
email: String!
catalog: UserCatalogRelation
decor: UserDecorRelation
decorSheet: UserDecorSheetRelation
}
There is an option to query with Fauna's FQL which may have a way of querying multiple IDs I will have to look into that, but would prefer to do this in graphQL with apollo if possible.
Thanks ahead of time
Thanks to support from FaunaDB
The following query and UDF does the trick
Query
type Query {
getMultipleDecors(DecorId: [ID!]): [Decor]
#resolver(name: "get_multiple_decors")
}
udf named get_multiple_decors
Query(
Lambda(
["input"],
Let(
{
data: Map(
Var("input"),
Lambda("x", Get(Ref(Collection("Decor"), Var("x"))))
)
},
Var("data")
)
)
)
If it's always exactly two ids, you can fetch both objects in a single query easily using field aliases:
const DECOR_SHEET = gql`
query GetDecorSheet($firstId: ID!, $secondId: ID!) {
firstDecorSheet: findDecorSheetByID(id: $firstId) {
refIdArray
sheetName
_id
}
secondDecorSheet: findDecorSheetByID(id: $secondId) {
refIdArray
sheetName
_id
}
}
`;
I am creating an ecommerce api using GraphQL. My prisma schema is
model Product {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
name String
price Int
stocks Int
}
model User {
id Int #id #default(autoincrement())
name String
email String #unique
password String
Orders Order[]
}
model Order{
id Int #id #default(autoincrement())
product Product #relation(fields: [productId], references: [id])
productId Int
user User #relation(fields: [userId], references: [id])
userId Int
##unique([productId, userId])
}
What should be my graphql schema and resolver function in order to create a relation whenever a user orders a product?
Your schema should actually look like this:
model Product {
id Int #id #default(autoincrement())
name String
price Int
stocks Int
orders Order[]
createdAt DateTime #default(now())
}
model User {
id Int #id #default(autoincrement())
name String
email String #unique
password String
orders Order[]
}
model Order {
id Int #id #default(autoincrement())
product Product #relation(fields: [productId], references: [id])
productId Int
user User #relation(fields: [userId], references: [id])
userId Int
##unique([productId, userId])
}
And your GraphQL mutation should contain the user id and product id being passed as variables and your resolver would look like this:
await prisma.user.update({
where: {
id: 1,
},
data: {
orders: {
create: {
product: {
connect: {
id: 123,
},
},
},
},
},
})
This will create a new order to the user id 1 and will add product id 123 to the order.