How do I query prisma relations while returning all fields on the parent object? - prisma

I am trying to return a post with all comments that have been approved. So I want all fields from the post object and all comments with approved set to true. It seems like this query is only giving me comments. How do I modify it to get what I want?
const post = await prisma.post.findUnique({
where: { slug },
select: { Comment: { where: { approved: true } } },
});
Thanks for any help.

You need to use include instead of select.
const post = await prisma.post.findUnique({
where: { slug },
include: {
Comment: {
where:{
approved: true
}
},
},
});
include defines which relations are included in the result that the Prisma Client returns: Reference

Related

How find in mongoose by an array property

I have defined my Conversation scheme like this:
const { Schema, model } = require("mongoose");
const ConversationSchema = Schema(
{
members: {
type: Array,
},
},
{ timestamps: true }
);
module.exports = model("Conversation", ConversationSchema);
My problem is that when I want to create a conversation model I search first if there is already a conversation.
const newConversation = async (req, res = response) => {
try {
const { senderId, receiverId } = req.body;
const conversation = await Conversation.find({
members: { $in: [senderId, receiverId] },
});
if (conversation.length === 0) {
const dbConversation = new Conversation({
members: [senderId, receiverId],
});
await dbConversation.save();
return res.status(201).json({
ok: true,
conversation: dbConversation
});
} else {
return res.status(403).json({
ok: false,
msg: "Conversation already exist",
});
}
} catch (err) {
return res.status(500).json({
ok: false,
msg: "Please contact with administrator",
});
}
};
senderId and receivedId are the ids of the users that are in that conversation, but it doesn't work.
How can I make it check if there is already a conversation with both ids?
Per the comments, we came to understand that the thing that wasn't working about the current code was always taking the code path that returned the message that the "Conversation already exist". This meant that the following query was always returning data:
const conversation = await Conversation.find({
members: { $in: [senderId, receiverId] },
});
The logic here does not match the logic implied in the question. This syntax uses the $in operator to find documents whose members array has at least one of the values passed to it (here the senderId and the receiverId).
To instead find documents where both of those people are present in the members array, you want to use the $all operator instead:
const conversation = await Conversation.find({
members: { $all: [senderId, receiverId] },
});
Working Mongo Playground example here.

Mongooose: How to get a id from a find array

I have a group-based document application, an error is happening in the sharing part. The application is composed of the following parts: Groups, viewers, users and documents.
A group can have many viewers and users, a user can have many documents. I'm working on the part where viewers can see all documents of users associated with the group the viewer is associated with
My controller
router.get("link", async (req, res) => {
const group = await Group.find({ viewer: req.session.userId }).select("id")
console.log(group); // This console.log returns the id in a array: [ { _id: new ObjectId("6323a88670c0dd9aaa5017d2") } ]
console.log(group.id); // This console.log returns undefined
const user = await User.find({ group: group.id });
console.log(user); // Nothing because the group.id is undefined
const documents = await Document.find({
user: user.id,
});
return res.render("page", {
documents,
});
Group schema
name: {
type: String,
required: true,
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true,
},
viewer: [{
type: mongoose.Schema.Types.ObjectId,
ref: "User",
}],
createdAt: {
type: Date,
default: Date.now,
}
I'm not able to retrieve the id from Group.find; what could be happening?
Because you want to have one value. So you can use findOne. Due to using findOne, you can reach group._id.
const group = await Group.findOne({ viewer: req.session.userId }).select("id")
console.log(group); { _id: new ObjectId("6323a88670c0dd9aaa5017d2") }
If you try to take the value from your array, you should take 0. element of array. Because it is an array and has elements. You are trying to reach element's id value.
But which element's id ? You need to declare it. Therefore, need to use group[0]._id. But if you want to reach just one element, using findOne() is better.
const group = await Group.find({ viewer: req.session.userId }).select("id")
console.log(group[0]); { _id: new ObjectId("6323a88670c0dd9aaa5017d2") }
I hope, it is clear and helps you. Good luck

Update a specific element in an array of objects in mongoDB

I am trying to add new fields in this array, and just update them when already existing but I can't manage to get it to work. I've been trying many things but the latest method I tried is this one below, that well... it doesn't work. Could anyone help me, please?
if (req.method === 'PATCH') {
const { title, description, socials } = req.body;
const { name, link } = socials;
try {
const user = await User.findOneAndUpdate(
{
email: process.env.EMAIL_USERNAME,
},
{
title,
description,
$set: {
socials: { name, link },
},
}
);
res.status(200).json({
status: 'success',
title,
description,
socials,
});
user.save();

Better way to perform this Relation "transaction" in Prisma

I posted a question yesterday that has the relevant prisma schema which can be found here.
As a follow up question, when a member creates a new Organization, I'd like for it to become their selected Membership. The only way I've found to do this is to deselect their current Memebership (set it to null), do the create, then restore the relationship if that create didn't work. I have to use updateMany for that initial operation in case there is no selectedMembership. Is that right?
//Deselect the currently selected Org
const updatedMembership = await prisma.membership.updateMany({
where: {
selectedById: user.id
},
data: {
selectedById: null
}
});
if (updatedMembership) {
//Select the new one.
const result = await prisma.organization.create({
data: {
name: body.name,
members: {
create: [{
role: MemberRole.OWNER,
userId: user.id,
selectedById: user.id
}]
}
},
});
if (result) {
res.status(200)
.json(result);
} else {
//Restore the previously selected one if the create failed
if(user.selectedMembership) {
await prisma.membership.update({
where: {
id: user.selectedMembership?.id
},
data: {
selectedById: user.id
}
});
}
res.status(500).end();
}
}
You can use the connect API to do all of this in a single query. Just make sure that the user.id is valid.
Here's a much cleaner version of the create and update query logic in your question:
const result = await prisma.organization.create({
data: {
name: body.name,
members: {
create: {
role: MemberRole.OWNER,
user: {
connect: {
id: user.id, // making the user a member of the organization
},
},
selectedBy: {
connect: {
id: user.id, // selecting the newly created membership as the user's default organization
},
},
},
},
},
});
This will handle all cases, regardless of whether the user with id = user.id currently:
Is a member of other organization(s) and has another membership as their default
Is a member of other organization(s) but has no default membership
Is not a member of any organization and has no default membership

Prisma splice Item from Array

I have been pushing updates to an array and was wondering if there is a built-in method to remove an entry from the array as well. Basically reversing the push command. I suspect that I have to query all documents and remove the item myself. But maybe there is some functionality I was unable to find inside the documentation.
Push:
const addTag = await prisma.post.update({
where: {
id: 9,
},
data: {
tags: {
push: 'computing',
},
},
})
Remove Expectation:
const removeTag = await prisma.post.update({
where: {
id: 9,
},
data: {
tags: {
splice: 'computing',
},
},
})
As of writing, there's no method to splice/remove items from a scalar list using Prisma. You would have to fetch the scalar list from your database, modify it manually in your application code and overwrite the record in your database with an update operation.
There is a feature request for this, please feel free to follow/comment with your use-case to help us track demand for this feature.
const { dogs } = await prisma.user.findOne({
where: {
id: userId
},
select: {
dogs: true
},
});
await prisma.user.update({
where: {
id: userId
},
data: {
dogs: {
set: dogs.filter((id) => id !== 'corgi'),
},
},
});