I'm new to GraphQL so I'm doing my first query and I'm trying to query for a nested key, email
Here is my schema
const UserLogin = new GraphQLObjectType({
name: 'UserLoginType',
fields: () => ({
login: { type: GraphQLString },
email: { type: GraphQLString },
}),
});
exports.UserType = new GraphQLObjectType({
name: 'UserType',
fields: () => ({
id: NotNullStringType,
name: { type: GraphQLString },
state: { type: GraphQLString },
login: { type: UserLogin },
}),
});
And what I'm trying to do is build a query that takes an email and searches for the UserType.login.email value and return the first value that matches that email or null.
Thanks!
Edit: In my redux/actions.js file I added:
export const fetchLoginsByEmail = (userEmail) => {
return createGraphqlAction(
{
query: `
query fetchUserByEmail($userEmail: String!) {
fetchUserByEmail(email: $userEmail) {
login {
email
}
state
name
id
}
}
`,
variables: {
userEmail,
}
},
FETCH_LOGINS_BY_EMAIL,
);
};
And in my query.js file I have this in my model.exports object:
fetchUserByEmail: {
type: UserType,
resolve: async (source, args, { user, loginId }) => {
if (!user) {
return null;
}
return serailize({
...user,
login: await getLogin(loginId),
});
},
},
It looks like you're missing the arguments parameter for your query resolver.
Update your query.js into something like:
fetchUserByEmail: {
type: UserType,
args: {
email { type: GraphQLString }
},
resolve: async (source, args, { user, loginId }) => {
// You can now use args.email here and filter your results with it
console.log(args.email);
if (!user) {
return null;
}
return serailize({
...user,
login: await getLogin(loginId),
});
},
},
Related
I want to display orderSchema in the frontend which is a subdocument. My subdocuments are objects which have a unique obiect id. As I am able to get the userSchema but not able to get orderSchema on the frontend do I need to make some changes in getServerSideProps function?
To take a deeper look you can checkout my repo - https://github.com/Sarab71/Git-optics
Model
import mongoose from 'mongoose'
const orderSchema = new mongoose.Schema({
rsph: { type: Number },
rcyl: { type: Number },
raxis: { type: Number },
lsph: { type: Number },
lcyl: { type: Number },
laxis: { type: Number },
add: { type: Number },
frame: { type: String },
lens: { type: String }
}, {
timestamps: true
});
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
phone: { type: Number, required: true },
address: { type: String, required: true },
orders: [orderSchema]
}, {
timestamps: true
});
export default mongoose.models.User || mongoose.model('User', userSchema)
Api
import User from "../../../models/addUser";
import initDB from "../../../helper/initDB";
initDB()
export default async (req, res) => {
switch (req.method) {
case "GET":
await getUser(req, res)
break;
}
}
const getUser = async (req, res) => {
const { uid } = req.query
const user = await User.findOne({ _id: uid })
res.status(200).json(user)
}
FrontEnd
I am using getServerSideProps for the FrontEnd
export async function getServerSideProps({ params: { id } }) {
const res = await fetch(`${baseUrl}/api/user/${id}`)
const data = await res.json()
return {
props: { user: data }
}
}
Im trying to create a sequalized query that Searches For a Team Name & Filter To Sport Type but when I test the JSON body on Postman I get an error and its not returning the data. The JSON body matches the data that its meant to return but its not matching up.
Test on Postman
{
"searchTerm": "Kaizer fc",
"sportType": "2"
}
teams.js
const Teams = require('../models').teams;
const {sequelize, QueryTypes } = require('sequelize');
const db = require('../models')
const search = (searchTerm, sportType) => {
return new Promise(async (resolve, reject) => {
try {
console.log("Testing");
const teams = await db.sequelize.query(
`SELECT teams.name, institutions.name, addresses.line1, addresses.line2, addresses.country
FROM teams
INNER JOIN institutions
ON teams.institution_id = institutions.id
INNER JOIN addresses
ON institutions.address_id = addresses.id
WHERE teams.name like :search_name and teams.sport_type_id LIKE :sport_type`,
{
replacements: { search_name: searchTerm, sport_type: sportType },
type: QueryTypes.SELECT
}
);
return resolve(teams);
} catch (err) {
return reject(err)
}
})
}
teams.js - Models Folder
'use strict';
module.exports = (sequelize, DataTypes) => {
const teams = sequelize.define('teams', {
name: { type: DataTypes.STRING, allowNull: false },
media_id: { type: DataTypes.STRING, allowNull: true },
state_id: { type: DataTypes.INTEGER, allowNull: true },
status_id: { type: DataTypes.INTEGER, allowNull: true },
sport_type_id: { type: DataTypes.INTEGER, allowNull: false },
created_by: { type: DataTypes.INTEGER, allowNull: true, references: { model: 'users', key: 'id' } },
modified_by: { type: DataTypes.INTEGER, allowNull: true, references: { model: 'users', key: 'id' } },
primary_user_id: { type: DataTypes.INTEGER, allowNull: true, references: { model: 'users', key: 'id' } },
institution_id: { type: DataTypes.INTEGER, allowNull: true, references: { model: 'institutions', key: 'id' } },
}, {
createdAt: 'created_at',
updatedAt: 'updated_at',
indexes: [
{
unique: true,
fields: ['id']
}
],
});
return teams;
};
search.js - Controllers
const helper = require('../utils/helper');
const teamsService = require('../services/teams');
const search = async (req, res) => {
try {
const data = await teamsService.search(req.body);
console.log("TESTING");
console.log(data);
return res.send(data);
} catch (err) {
return helper.handleError(err, req, res);
}
}
module.exports = search;
search function has two arguments: searchTerm and sportType and you pass the whole req.body as a first argument so that's why it becomes a value for searchTerm and you got this error about the whole value from Sequelize.
Just extract both props from req.body OR define search with props passed by as an object:
const { searchTerm, sportType } = req.body;
const data = await teamsService.search(searchTerm, sportType);
OR
const data = await teamsService.search(req.body);
...
const search = ({ searchTerm, sportType }) => {
return new Promise(async (resolve, reject) => {
I'm not sure which part I might be doing wrong. I was hoping to get some advice.
The query I am using in GraphiQL is:
query getUser($id:Int!) {
user(id:$id) {
id
email
}
}
For the backend I am using NodeJS. I am also declaring the user type as:
const UserType = new GraphQLObjectType({
name: 'User',
fields: () => ({
id: { type: GraphQLID },
email: { type: GraphQLString }
})
});
My root query is:
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
user: {
type: UserType,
args: { id: { type: GraphQLInt } },
resolve(parentValue, args) {
const query = `SELECT * FROM users WHERE id=$1`;
const values = [ args.id ];
dbQuery.query(query, values).then(({ rows }) => {
console.log(rows[0]);
return rows[0];
});
}
}
}
});
const schema = new GraphQLSchema({ query: RootQuery });
app.use(
'/api/v1/graphql',
graphqlHTTP({
schema: schema,
graphiql: true
})
);
What I get in return is:
{
"data": {
"user": null
}
}
I was hoping to know what I might be doing wrong that is resulting in null being returned instead of the data that I am querying from the database.
Thank you for all the help.
It will be much more clear if you use with await
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
user: {
type: UserType,
args: { id: { type: GraphQLInt } },
resolve: async(parentValue, args) {
const query = `SELECT * FROM users WHERE id=$1`;
const values = [ args.id ];
const rows = await dbQuery.query(query, values);
return rows[0];
}
}
}
});
When using a promise and returning anything inside the promise will only return the result to the promise that is executed. It will not be returning as a whole to the parent function.
You can also return the whole promise function like below
return dbQuery.query(query, values)
This question already has answers here:
Why does a GraphQL query return null?
(6 answers)
Closed 3 years ago.
I tried to practised some GrahpQL and I am stuck...
I want to take one object from api list but grahpql returning null.
Used async/await doesn't help.
There is no problems with returning all list but with single element.
const axios = require('axios');
const {
GraphQLObjectType,
GraphQLInt,
GraphQLString,
GraphQLList,
GraphQLSchema
} = require('graphql');
// Country basic info
const CountryInfo = new GraphQLObjectType({
name: "CountryInfo",
fields: () => ({
name: { type: GraphQLString },
capital: { type: GraphQLString },
population: { type: GraphQLInt },
flag: { type: GraphQLString },
})
})
// Root Query
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
countryList: {
type: new GraphQLList(CountryInfo),
resolve(parent, args) {
return axios.get('https://restcountries.eu/rest/v2/all').then( res => res.data );
}
},
country: {
type: CountryInfo,
args: {
name: { type: GraphQLString }
},
async resolve(parent, args) {
const element = await axios.get(`https://restcountries.eu/rest/v2/name/${args.name}`).then(res => res.data);
return element;
}
},
},
});
module.exports = new GraphQLSchema({
query: RootQuery,
});
If you look at the response coming from the REST endpoint, what's being returned is an array of countries, and not just a single country object. Your resolver cannot return an array unless the type of the field is a List. Similarly, if the type of the field is a List, you cannot return an object in your resolver. This should work:
country: {
type: CountryInfo,
args: {
name: { type: GraphQLString }
},
async resolve(parent, args) {
const elements = await axios.get(`https://restcountries.eu/rest/v2/name/${args.name}`).then(res => res.data);
return elements[0];
}
},
i'm trying to add authentication to my app using jwt token. I've created a LoginMutation with the FIELDS_CHANGE type but it looks like relay doesn't hook it up with the existing model.
I've listed my relay mutation and schema mutation.
My LoginMutation:
import Relay from 'react-relay';
export default class LoginMutation extends Relay.Mutation {
static fragments = {
viewer: () => Relay.QL`
fragment on User {
id
}
`
};
getMutation() {
return Relay.QL`mutation{loginUser}`;
}
getFatQuery() {
return Relay.QL`
fragment on LoginPayload {
viewer {
userId
email
password
jwt_token
}
}
`;
}
getConfigs() {
return [{
type: 'FIELDS_CHANGE',
fieldIDs: {
viewer: this.props.viewer.id
}
}];
}
getVariables() {
// inputs to the mutation
return {
email: this.props.credentials.email,
password: this.props.credentials.password
};
}
getOptimisticResponse() {
return {
viewer: {
email: this.props.credentials.email
}
};
}
}
const loginMutation = mutationWithClientMutationId({
name: 'Login',
inputFields: {
email: {
type: new GraphQLNonNull(GraphQLString)
},
password: {
type: new GraphQLNonNull(GraphQLString)
}
},
outputFields: {
viewer: {
type: userType,
resolve: (user) => user
}
},
mutateAndGetPayload: ({ email, password }, request) => {
return getUserByCredentials(email, password)
.then((user) => {
if (!user) {
return newUser;
}
user.jwt_token = jwt.sign({
id: user.id,
name: user.name,
email: user.email
}, JWT_SECRET);
return user;
})
.catch((error) => { throw error; });
}
});