In prisma 1 I have used fragment to fetch the nested fields.
For example:
const mutations = {
async createPost(_, args, ctx) {
const user = await loginChecker(ctx);
const post = await prisma.post
.create({
data: {
author: {
connect: {
id: user.id,
},
},
title: args.title,
body: args.body,
published: args.published,
},
})
.$fragment(fragment);
return post;
},
};
but seems like in prisma2 it is not supported. because by running this on playground,
mutation CREATEPOST {
createPost(
title: "How to sleep?"
body: "Eat, sleep, repaet"
published: true
) {
title
body
published
author {
id
}
}
}
I am getting,
"prisma.post.create(...).$fragment is not a function",
The include option is used to eagerly load relations in Prisma.
Example from docs:
const result = await prisma.user.findOne({
where: { id: 1 },
include: { posts: true },
})
Assuming a user table with a one-to-many posts relation, this will return back the user object with the posts field as well.
Prisma also supports nesting as well, for example:
const result = await prisma.user.findOne({
where: { id: 1 },
include: {
posts: {
include: {
author: true,
}
},
},
})
Related
I have a project management application built with React and GraphQL for which the Github repo can be found here. One of the functionalities allows for deleting a project.
I am trying to update the cache when I delete an individual project.
const [deleteProject] = useMutation(DELETE_PROJECT, {
variables: { id: projectId },
update(cache, { data: { deleteProject } }) {
const { projects } = cache.readQuery({ query: GET_PROJECTS });
cache.writeQuery({
query: GET_PROJECTS,
data: {
projects: projects.filter(
(project) => project.id !== deleteProject.id
),
},
});
},
onCompleted: () => navigate("/"),
});
However, when I attempt to do so, I am getting the following error: Error: Cannot destructure property 'projects' of 'cache.readQuery(...)' as it is null
Can someone help me figure out what's going on? This is what the getProjects query looks like:
const GET_PROJECTS = gql`
query getProjects {
projects {
id
name
description
status
}
}
`;
Here is the root query:
const RootQuery = new GraphQLObjectType({
name: "RootQueryType",
fields: {
projects: {
type: new GraphQLList(ProjectType),
resolve(parent, args) {
return Project.find();
},
},
project: {
type: ProjectType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
return Project.findById(args.id);
},
},
clients: {
type: new GraphQLList(ClientType),
resolve(parent, args) {
return Client.find();
},
},
client: {
type: ClientType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
return Client.findById(args.id);
},
},
},
});
I'm new to Apollo (back-end in general) so your patience is appreciated; I've looked through Apollo's docs and I'm not sure where I've gone wrong.
The data I'm receiving from my REST API call is as follows - I'm trying to return the ids and titles and based on my trials, I'm fairly certain the issue is my resolvers? The error I'm receiving is: "Cannot read properties of undefined (reading: 'session')"
{
"selection": {
...other data...
"options": [
{
id: 1
title: "Option 1 Title"
},
{
id: 2
title: "Option 2 Title"
},
]
}
}
My schema:
type Query {
session: Selection
}
type: Selection {
...other data...
optionListing: [Options]
}
type: Options {
id: Int
title: String
}
My resolvers:
{
Query: {
session: async (parent, args, {tokenAuth}) => {
...token auth code....
return tokenAuth;
};
}
Selection: {
optionListing: async ({tokenAuth}) => {
...this is the resolver that triggers the API call...
return optionData;
}
}
Options: {
id: async(parent) => {
const tempID = await parent;
return tempID.id;
}
title: async(parent) => {
const tempTitle = await parent;
return tempTitle.title;
}
}
}
I am trying to refetch the data after an action is done but i am failing at refetching and the page is not refreshing with the data.
Below is the code for mutation and fetch queries:
const {
data: designHubProjectData,
loading: designHubProjectDataLoading,
error: designHubProjectDataError
} = useQuery(ALL_DESIGNHUB_PROJECTS, {
fetchPolicy: 'network-only',
variables: {
order: [{ projectNumber: 'DESC' }]
}
});
const [insertEmployeeDesignHubProjectBookmarkMutation] = useMutation(
INSERT_EMPLOYEE_DESIGNHUB_PROJECT_BOOKMARK,
{
refetchQueries: [ // here i am calling two queries after insert
{
query: EMPLOYEE_DESIGNHUB_PROJECT_BOOKMARK,
variables: {
order: [{ projectNumber: 'DESC' }]
}
},
{
query: ALL_DESIGNHUB_PROJECTS,
fetchPolicy: 'network-only',
variables: {
order: [{ projectNumber: 'DESC' }]
}
}
]
}
);
and then below is the method where i am calling above mutation
const handleAddBookmark = record => {
insertEmployeeDesignHubProjectBookmarkMutation({
variables: {
employeeId: loggedInEmployee.id,
projectNumber: record.projectNumber
}
}).then(({ data }) => {
if (data.insertEmployeeDesignHubProjectBookmark.ok) {
notification.success({
message: 'Success',
description: 'Successfully bookmarked the project.'
});
} else {
const errors = data.insertEmployeeDesignHubProjectBookmark.errors.join(', ');
notification.error({
message: 'Error',
description: `Adding bookmark to the project failed: ${errors}.`
});
}
});
};
i am not sure where I am doing wrong with the above code. Could any one please let me know any suggestion or ideas how to refetch make it work, many thanks in advance
I have solved this problem by assigning refetch to Oncompleted method like as below,
const {
data: designHubProjectBookmarkData,
loading: designHubProjectBookmarkDataLoading,
error: designHubProjectBookmarkDataError,
refetch: refetchBookmarkProjects
} = useQuery(EMPLOYEE_DESIGNHUB_PROJECT_BOOKMARK, {
fetchPolicy: 'network-only',
variables: {
order: { projectNumber: 'DESC' }
}
});
const [insertEmployeeDesignHubProjectBookmarkMutation] = useMutation(
INSERT_EMPLOYEE_DESIGNHUB_PROJECT_BOOKMARK,
{
onCompleted: refetchBookmarkProjects
}
);
if it incase anyone in the future looking for the same, this is an example.
can anyone help me how to add multiple "Addons" per create ?
With this code I can add only one addons ..
(Tested in postman) but can anyone suggest me how I can make it to add multiple addons ?
Model
const itemSchema = new mongoose.Schema({
name: {
type:String
},
price:{
type:Boolean
},
addons:[{
addonsName:{
type:String
},
price:{
type:String
}
}]
})
Controller :
const addItem = await Item.create({
name:req.body.name,
price: idOfGroup,
addons:[{addonsName:req.body.addonsName, price: req.body.price}]
});
res.status(200).json({status:'Success',addItem})
I "fix" it doing
const addItem = await Item.create(req.body);
And in postman I write
{
"name":"Test1",
"addons" : [
{
"addonsName":"Test",
"price":"100"
},
{
"addonsName":"TestTest",
"price":"200"
}
]
}
But Is this the wrong way of using .Create() ?
According to your postman sample, you're passing the addons array under the key addons. So just pass that as the addons:
const addItem = await Item.create({
name: req.body.name,
price: idOfGroup,
addons: req.body.addons,
});
res.status(200).json({ status: "Success", addItem });
You could additionally use object destructuring to get rid of the req.body. repetition:
const { name, addons } = req.body;
const addItem = await Item.create({
name,
price: idOfGroup,
addons,
});
res.status(200).json({ status: "Success", addItem });
you can make the addons as Array like below you can see
const itemSchema = new mongoose.Schema({
name: {
type:String
},
price:{
type:Boolean
},
addons:[]
)}
In controller:
const addItem = await Item.create({
name:req.body.name,
price: idOfGroup,
addons:req.body.addons
});
res.status(200).json({status:'Success',addItem})
Postman request payload:
{
"name":"Test1",
"addons" : [
{
"addonsName":"Test",
"price":"100"
},
{
"addonsName":"TestTest",
"price":"200"
}
]
}
I'm trying to add a route /me to get user authenticated information. This is what I have at my files.
I've tried adding a route /me at users.services file, but I'm getting this error: "error: MethodNotAllowed: Method find is not supported by this endpoint."
I want to get response with a user object (based on token) to a GET method to route '/me'.
users.service.js
// Initializes the `users` service on path `/users`
const createService = require('feathers-sequelize');
const createModel = require('../../models/users.model');
const hooks = require('./users.hooks');
module.exports = function (app) {
const Model = createModel(app);
const paginate = app.get('paginate');
const options = {
name: 'users',
Model,
paginate
};
// Initialize our service with any options it requires
app.use('/users', createService(options));
app.use('/me', {
get(id, params) {
return Promise.resolve([
{
id: 1,
text: 'Message 1'
}
])
}
})
// Get our initialized service so that we can register hooks and filters
const service = app.service('users');
service.hooks(hooks);
};
users.hooks.js
const { authenticate } = require('#feathersjs/authentication').hooks;
const {
hashPassword, protect
} = require('#feathersjs/authentication-local').hooks;
module.exports = {
before: {
all: [ ],
find: [ authenticate('jwt') ],
get: [],
create: [ hashPassword() ],
update: [ hashPassword() ],
patch: [ hashPassword() ],
remove: []
},
after: {
all: [
// Make sure the password field is never sent to the client
// Always must be the last hook
protect('password')
],
find: [],
get: [],
create: [],
update: [],
patch: [],
remove: []
},
error: {
all: [],
find: [],
get: [],
create: [],
update: [],
patch: [],
remove: []
}
};
users.model.js
// See http://docs.sequelizejs.com/en/latest/docs/models-definition/
// for more of what you can do here.
const Sequelize = require('sequelize');
const DataTypes = Sequelize.DataTypes;
module.exports = function (app) {
const sequelizeClient = app.get('sequelizeClient');
const users = sequelizeClient.define('users', {
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
password: {
type: DataTypes.STRING,
allowNull: false
},
}, {
hooks: {
beforeCount(options) {
options.raw = true;
}
}
});
users.associate = function (models) { // eslint-disable-line no-unused-vars
// Define associations here
// See http://docs.sequelizejs.com/en/latest/docs/associations/
};
return users;
};
What you did through
app.use('/me', {
get(id, params) {
return Promise.resolve([
{
id: 1,
text: 'Message 1'
}
])
}
})
Was implement routes for /me/:id. The find method is what runs for the base route of /me.
I don't think a separate service is really necessary though. An easier solution would be to use a before all hook that changes the id if you are accessing /users/me:
module.exports = function() {
return async context => {
if(context.id === 'me') {
context.id = context.params.user._id;
}
}
}