Prisma.js mongodb relation filter doesn't work - mongodb

I have a model Post that looks like this:
model Post {
id String #id #default(auto()) #map("_id") #db.ObjectId
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
...
...
...
LikedPosts LikedPost[]
}
and model LikedPost that looks like this:
model LikedPost {
id String #id #default(auto()) #map("_id") #db.ObjectId
createdAt DateTime #default(now())
post Post #relation(fields: [postId], references: [id])
postId String
user User #relation(fields: [userId], references: [id])
userId String
##unique([userId, postId])
}
I'm trying to return all posts that user liked inside db.post.findMany with this prisma filter:
where: {
LikedPosts: {
some: {
userId: {
equals: session.userId as string,
},
},
},
},
But it always returns empty array as a result.
Even if I put raw value instead of session.userId like "62d6b8d220ba0fa6d5cea60f" of the user that has liked posts, it still returns nothing.
It doesn't even work inside Prisma Studio.
Am I doing something wrong here?

The answer was to add #db.ObjectId to the userId field in prisma Schema like this:
model LikedPost {
id String #id #default(auto()) #map("_id") #db.ObjectId
createdAt DateTime #default(now())
post Post #relation(fields: [postId], references: [id])
postId String #db.ObjectId
user User #relation(fields: [userId], references: [id])
userId String #db.ObjectId
##unique([userId, postId])
}

Related

Creating self relation in prisma

I want to add a self relation on my user table but it seems there is an issue with the way am doing it.
model User {
id BigInt #id(map: "user_pkey") #unique(map: "user_id_key") #default(autoincrement())
firstname String? #db.VarChar
lastname String? #db.VarChar
username String? #unique #db.VarChar
email String? #db.VarChar
password String? #db.VarChar
organization String? #db.VarChar
createdAt DateTime? #db.Timestamptz(6)
updatedAt DateTime? #db.Timestamptz(6)
parent_id BigInt?
deletedAt DateTime? #db.Timestamptz(6)
deleted_by BigInt?
##map("users")
parent User? #relation(fields: [parent_id], references: [id]) // this line gives me error
}
I see the following error :
```Error validating field parent in model User: The relation field parent on model User is missing an opposite relation field on the model User. Either run prisma format or add it manually.
What am i doing wrong here?
Can you try this schema?
model User {
id BigInt #id(map: "user_pkey") #unique(map: "user_id_key") #default(autoincrement())
firstname String? #db.VarChar
lastname String? #db.VarChar
username String? #unique #db.VarChar
email String? #db.VarChar
password String? #db.VarChar
organization String? #db.VarChar
createdAt DateTime? #db.Timestamptz(6)
updatedAt DateTime? #db.Timestamptz(6)
parent_id BigInt?
deletedAt DateTime? #db.Timestamptz(6)
deleted_by BigInt?
parent User? #relation("UserParent", fields: [parent_id], references: [id]) // this line gives me error
usersAsParents User[] #relation("UserParent")
##map("users")
}
For reference, here is a guide on Self-Relations.

How to model a tournament in Prisma

I want to model a tournament in Prisma. I have this:
model Tournament {
id Int #id #default(autoincrement())
meets Meet[]
}
model Meet {
id Int #id #default(autoincrement())
name String
matches Match[]
}
model Match {
id Int #id #default(autoincrement())
player1Id Int
player2Id Int
meet Meet #relation(fields: [meetId], references: [id])
meetId Int
}
model Player {
id Int #id #default(autoincrement())
name String
}
model Result {
id Int #id #default(autoincrement())
matchId Int
playerId Int
}
I feel the Match model might need to link player1 and player2 (with a relation) to the Player model. I'm also not sure how the result should be modelled.
Any advice will be appreciated.
You can do it as follow:
datasource mysql {
provider = "mysql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
generator erd {
provider = "prisma-erd-generator"
output = "./entity-relationship-diagram.svg"
}
model Tournament {
id Int #id #default(autoincrement())
name String
meets Meet[] #relation()
}
model Meet {
id Int #id #default(autoincrement())
name String
tournament Tournament #relation(fields: [tournamentId], references: [id])
tournamentId Int
matches Match[] #relation()
}
model Match {
id Int #id #default(autoincrement())
name String
meeet Meet #relation(fields: [meetId], references: [id])
meetId Int
players Player[] #relation("matchPlayers", fields: [playerId], references: [id])
playerId Int
winner Player? #relation("matchWinner", fields: [winnerId], references: [id])
winnerId Int?
score Score[] #relation()
}
model Player {
id Int #id #default(autoincrement())
name String
matchesPlayers Match[] #relation("matchPlayers")
matchesWinner Match[] #relation("matchWinner")
score Score[] #relation()
}
model Score {
id Int #id #default(autoincrement())
score Int
match Match #relation(fields: [matchId], references: [id])
matchId Int
player Player #relation(fields: [playerId], references: [id])
playerId Int
}
And it will generate the following database

EF Code First Multiple Tables to single entity

I'm just starting out with Entity Framework and I seem to be misunderstanding something. Basically I've got a database already setup. Let's say the following are my tables.
**Employees**
EmployeeId
CubeId (FK to Cubes table)
NameId (FK to Name table)
**Cubes**
CubeId
CubeName
**Person**
NameId
FirstName
LastName
I want to be able to write something like this: SELECT EmployeeId, CubeId, CubeName, FirstName, LastName FROM Employees LEFT OUTER JOIN Cubes LEFT OUTER JOIN Person. So it would return all of the Employees. Basically, in EF Code First do you have to create a class for EVERY table? If not, how do you create a LEFT OUTER Join equivalent? All of the examples I've found use navigational properties to go from table to table (i.e. class to class).
Models:
public class Employee
{
[Key]
public int EmployeeId {get;set;}
public int CubeId {get;set;}
[ForeignKey("Cube")]
public int NameId {get;set;}
[ForeignKey("Name")]
public virtual Cube Cube {get;set;}
public virtual Name Name {get;set;}
}
public class Cube
{
[Key]
public int CubeId {get;set;}
public string CubeName {get;set;}
}
public class Name
{
[Key]
public int NameId {get;set}
public string FirstName {get;set;}
public string LastName {get;set;}
}
Your context:
public class YourContext:DbContext
{
public DbSet<Name> Names {get;set;}
public DbSet<Cube> Cubes {get;set;}
public DbSet<Employee> Employees {get;set;}
}
Your query:
YourContext db = new YourContext();
var query = db.Employees.Where(x => x.EmployeeId == id).Select(x => new
{
EmployeeId = x.EmployeeId,
CubeId = x.Cube.CubeId,
CubeName = x.Cube.CubeName,
FirstName = x.Name.FirstName,
LastName = x.Name.LastName
}).FirstOrDefault();
This will locate first employee that has some id (or return null if there's none), and then create a type that has all the properties you mentioned. If you need last name, you access it with:
string lastName = query.LastName;

Code First attribute for referring to a "user" by "author" in a "post" model

I have POCO models User and Post.
The post has an Author which really is a User, but I would like the Post model to refer to the user via the Author property.
I suspect I can tell EF that Author and AuthorId are really User and UserId with an attribute, the problem is that I don't know how.
EDIT:
Allow me to demonstrate.
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public int AuthorId { get; set; }
public virtual User Author { get; set; }
}
I would like AuthorId to be the Id matching the User Id.
you don't need to use attribute for that. If you Inherit Author from User EF will do this all for you. And you don't need to have authorId in author class because It already have a uniqe Id (UserId).
http://msdn.microsoft.com/en-us/library/cc716779.aspx

Autogenerate primary key (Guid) Entity Framework CTP5

I have a following POCO class
public class Account
{
[Key,DatabaseGenerated(DatabaseGenerationOption.Identity)]
public string AccountId { set; get; }
public string FirstName { set; get; }
public string LastName { set; get; }
public string Email { set; get; }
}
I get the following exception when the database gets created
Identity column 'AccountId' must be of data type int, bigint, smallint, tinyint, or decimal or numeric with a scale of 0, and constrained to be nonnullable.
Shouldn't you have:
[Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid AccountId { set; get; }
?
Jeff's answer is right. Just a little tip for you. Using EF6 I wrote next configuration in order to set all fields with name "Id" and type "Guid" as identity.
modelBuilder.Properties<Guid>()
.Where(info => info.Name.ToLower()== "id")
.Configure(configuration => configuration.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity));
So I don't have to write [DatabaseGenerated(DatabaseGenerationOption.Identity)] everytime.
Sound like you have to update your AccountId property from string to one of the mentioned datatypes in the exception:
int, bigint, smallint, tinyint, or decimal or numeric with a scale of 0, and constrained to be nonnullable
Any reason why it's now a string?