How to filter by relationships using each Prisma orm - orm

I have a one to many relationship, and I need to filter the relationship values, I need to bring all the records that contain all the values ​​of the array/
example: const attributes = ["Car", "Bike", "Truck"]
prisma.car.findMany({
where: {
attribute: {
typeCar: {
every: {
value: { hasSome: attributes },
},
},
},
},
});
This search works only if all attributes exist, if any attribute does not exist, nothing is returned
I need it to return the record, even if typeCar does not contain all records.
How could I do that with the prisma?
My model
model Car {
id String #id
name String
status String
description String
thumbnailUrl String?
groupId String?
categoryName String
attribute Attribute[]
images CarImage[]
createdAt DateTime #default(now())
updatedAt DateTime? #updatedAt
##map("car")
}
model Attribute {
id String #id
typeCar String[]
car Car? #relation(fields: [carId], references: [id])
carId String?
createdAt DateTime #default(now())
updatedAt DateTime? #updatedAt
##map("attributeProductValue")
}

One solution I found was to add a new field in the car table. Saving the values ​​of the typeCar
model Car {
id String #id
name String
status String
description String
thumbnailUrl String?
groupId String?
categoryName String
attribute Attribute[]
images CarImage[]
typeCarValues String[]
createdAt DateTime #default(now())
updatedAt DateTime? #updatedAt
##map("car")
}
So I can filter without going through the relationship, and the hasEvery option works.
example: const attributes = ["Car", "Bike", "Truck"]
prisma.car.findMany({
where: {
typeCarValues: {
hasEvery: attributes,
},
},
})
The problem was in filtering the relationship in attributes using every and then hasEvery, to return the value all attributes of typeCar need to be informed and exist, if any of them is not informed, it does not return.

Related

Generated types in Prisma do not have optional fields as defined in the schema

Using Prisma v 3.8.1
My User Model is
model User {
id Int #id #default(autoincrement())
createdAt DateTime? #default(now())
email String #unique
name String
password String
accessToken String?
accessTokenCreatedAt DateTime? #default(now())
address String?
city String?
state String?
postalCode String?
phoneNumber Int?
igUserId String?
role Role #relation(fields: [roleId], references: [id])
roleId Int
organization Organization? #relation(fields: [organizationId], references: [id])
organizationId Int?
orders Order[]
}
Generated type is
type User = {
id: number;
createdAt: Date | null;
email: string;
name: string;
password: string;
accessToken: string | null;
accessTokenCreatedAt: Date | null;
address: string | null;
city: string | null;
state: string | null;
postalCode: string | null;
phoneNumber: number | null;
igUserId: string | null;
roleId: number;
organizationId: number | null;
}
There are no optional fields in this type as described in the model, not even for the autogenerated id field. So while using this type in my code, I keep getting this error
Type '{ name: any; email: any; password: string; roleId: number; }' is missing the following properties from type 'User': id, createdAt, accessToken, accessTokenCreatedAt, and 7 more.
Expected behaviour: Optional fields should be marked optional ? in the generated typescript Types so that its easy in the code to only set the required fields and pass it to .create() method
This type is not intended to use with create or similar methods. It's return type of find* methods and such. It's supposed to match DB table and table does not have undefined or optional rows, only nullable or not.
If you look carefully you can find other types, for example, UserCreateArgs with data property which will be used for create method. And that type has optional fields exactly how you want it to be.
What I don't understand is where you got this error from? Have you tried to use the types for your own wrappers?

Having a hard time with Prisma/Graphql One to One and One to many

I have a lot of trouble figuring out the 1 to 1 and 1 to many relation i made this schema then I have my graphql derived from that
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model Games {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
short_hand String #unique #db.VarChar(255)
name String #unique #db.VarChar(255)
in_boxes Box[]
set Sets[]
}
model User {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
username String #unique #db.VarChar(255)
password String #db.VarChar(255)
role Role #default(USER)
first_name String? #db.VarChar(255)
last_name String? #db.VarChar(255)
store String? #db.VarChar(255)
boxes Box[]
}
model Store {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
name String #unique #db.VarChar(255)
}
model Box {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
box_number String #db.VarChar(100)
box_second_number String? #db.VarChar(100)
set String #db.VarChar(255)
set_list Sets #relation(fields: [set], references: [name])
gameid Int? #default(1)
game Games? #relation(fields: [gameid], references: [id])
User User? #relation(fields: [userId], references: [id])
userId Int?
}
model Sets {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
name String #unique #db.VarChar(255)
code String #unique #db.VarChar(255)
children String[]
in_boxes Box[]
game String? #db.VarChar(255)
gamerel Games? #relation(fields: [game], references: [short_hand])
edition String?
}
enum Role {
USER
ADMIN
CHRIS
}
Basically a user will have boxes that they own (
The boxes has a Game Type and contains a parent Set which
Has it own set code and contain set children (array)
The game type it self has only name and shortcode
My main issue is that when I try to create a set with the resolver code
the graphql
mutation {
createBox (input:{box_number:"001", secondary_number:"A", game:{name:"yu"}, set:"Crucibile of War Unlimit"}) {
box_number
set
game
id
}
}
the resolver
createBox: async (_: any, { input }: any, context: Context) => {
const find = await context.prisma.games.findFirst({
where: {name: {contains:input.game[0].name,
mode:"insensitive"}}
}
);
console.log(find);
console.log(input.set);
return await context.prisma.box.create({
data: {
box_number: input.box_number,
box_second_number: input.secondary_number,
gameid: find?.id,
set: {connect: {
name: input.set
},
},
},
});
},
I get
" Foreign key constraint failed on the field: `Box_set_fkey (index)`",
" at cb
I'm really confused on how to make it work
In this case, set directly expects the relation so you don't need connect here. This should work:
const find = await prisma.games.findFirst({
where: { name: { contains: input.game[0].name } },
})
await prisma.box.create({
data: {
box_number: input.box_number,
box_second_number: input.secondary_number,
gameid: find?.id,
set: input.set,
},
})

One-to-many relation with additional field

I am creating a schema in prisma with the model User and Guild.
User can have one guild or none
Guild can have multiple User
Now I want to add an additional field of the role a user have in the guild.
What would be the best to achieve this?
I could add them to the user but then I have to manage it in the code that all are null or not null.
enum GuildRole {
MEMBER
CO_LEADER
LEADER
}
model Guild {
id Int #id #default(autoincrement())
name String
users User[]
}
model User {
id Int #id #default(autoincrement())
username String? #unique
guild Guild? #relation(fields: [guildId], references: [id])
guildId Int?
guildRole GuildRole?
}
You can do it as following when adding an existing user to a guild.
import { PrismaClient, GuildRole } from '#prisma/client'
const prisma = new PrismaClient()
// add user to guild
const addAnExistingUserToAGuild = async (userId: number, guildId: number, guildRole: GuildRole) => {
return await prisma.user?.create({
data: {
guildId: guildId,
userId: userId,
guildRole: guildRole,
},
})
}
The modelling will completely depend on your personal/company preference/style, I've modelled your schema like this :
enum GuildRole {
MEMBER
CO_LEADER
LEADER
}
model User {
userId Int #id #default(autoincrement())
username String? #unique
guild Guild? #relation(fields: [guildId], references: [guildId])
guildId Int?
guildRole GuildRole?
}
model Guild {
guildId Int #id #default(autoincrement())
name String
users User[]
}
More examples in our docs here for how you can create a one-to-many relationship :
https://www.prisma.io/docs/concepts/components/prisma-schema/relations/one-to-many-relations

How to set Default value in MVC 4 razor DropDownListFor

I Have MVC Razor view with lot of DropDrownFor.
i wanna set default value to that DropdownListFor.
This is my View:
#Html.DropDownListFor(model => model.DestCountryId, ViewBag.CountryIdList as SelectList, "select", new { #class = "form-control input-sm" })
This is my ViewBag:
ViewBag.CountryIdList = new SelectList(db.Countries.Where(a => a.Currency != null), "Id", "Name");
Ho w to set Default value in this scenario
you need to do like this:
ViewBag.CountryIdList = new SelectList(db.Countries.Where(a => a.Currency != null), "Id", "Name",1);
For Example in the Countries List, you have a item CountryName and its id is 1, you need to pass the 1 in the last parameter, and element with that Id 1 will be shown selected by default.
Example:
public class Country
{
public int Id { get; set; }
public string Name { get; set; }
}
List<Country> list = new List<Country>();
list.Add(new Country{ Id = 1, Name="Test"});
list.Add(new Country{ Id = 2, Name="Test2"});
now in controller action:
int Selected = 2;
ViewBag.CountryIdList = new SelectList(list, "Id", "Name",Selected);
Now the Test2 will be shown selected default in View.
The first parameter that you give to #Html.DropDownListFor is an expression that identifies the object that contains the properties to display.
You have already given "Selected" as default value if nothing is selected or your DestCountryId doesn't hold any value or it doesn't matches with the values passed in the CountryIdList. You need to assign a value to DestCountryId before rendering this view. You can do this either in controller or where you build your view-model like:
viewModel.DestCountryId = 33; where this value exists in the selectList value that you are giving to dropdownlist.
Also, a good practise is to not to use ViewBag. Try creating a simple model with properties that your current view needs.
You can also use SelectList(IEnumerable, String, String, Object) overload of SelectList where the object is the selected value.
Hope this helps.

How to get single row from SQLite database in Windows Store apps?

If I want single primitive value like int, string, float etc I can do like this.
using (var db = new SQLiteConnection(DbPath))
{
double i = db.CreateCommand("select salary from PersonMaster where personId = ?", 9).ExecuteScalar<double>();
}
If I try to return whole object of person master i.e. single row the below code returns null
using (var db = new SQLiteConnection(DbPath))
{
PersonMaster objPersonMaster = db.CreateCommand("select * from PersonMaster where personId = ?", 9).ExecuteScalar<PersonMaster>();
}
I compulsory have to use this
using (var db = new SQLiteConnection(DbPath))
{
List<PersonMaster> lstPersonMaster = db.Query<PersonMaster>("select * from PersonMaster where personId = ?", 9);
PersonMaster objPersonMaster = lstPersonMaster.First();
}
Is there any way to get single row as object, rather than dealing with List<T>
I am assuming you are using SQLite-Net. If that is the case you can use the Find method. Find gets an object using its primary key.
The personId field needs the PrimaryKey attribute as follows:
public class PersonMaster
{
[PrimaryKey]
public int personId { get; set; }
public string name { get; set; }
public decimal salary { get; set; }
}
Then you can use Find like so:
// get person 9
PersonMaster person9 = db.Find<PersonMaster>(9);
You can either use "TOP(1) yourquery" or "yourquery LIMIT 1"
if you just want to get rid of the list step, you can do it directly:
PersonMaster objPersonMaster = db.Query<PersonMaster>("select * from PersonMaster where personId = ?", 9).First();
Of course you have to deal with a possible exception in case nothing is returned, but you should do this also with the list approach anyway.