Search for particular results with a certain string in GraphQL - javascript

I want to search with my query getFoodType to return results based on whether the foodType of particular restaurant/takeaway is a "Chicken","Pizza" etc
Like this foodType: "Chicken"
I've tried using arguments and mongoDB filters (it's a MongoDB server) but no luck.
Schema
const EaterySchema = new Schema({
name: {
type: String,
required: true
},
address: {
type: String,
required: true
},
foodType: {
type: String,
required: true
}
});
My Schema Types
type Eatery {
id: String!
name: String!
address: String!
foodType: String!
}
type Query {
eatery(id: String!): Eatery
eateries: [Eatery]
getFoodType(foodType: String): [Eatery]
}
My Resolver
getFoodType: () => {
return new Promise((resolve, reject) => {
Eatery.find({})
.populate()
.exec((err, res) => {
err ? reject(err) : resolve(res);
});
});
},
Current Query in Apollo Playground
{
getFoodType (foodType: "Chicken") {
id
name
address
foodType
}
}
I essentially want to return all the results with "Chicken" as a the foodType. Something like foodType: "Chicken".

First, you need to get the value of the foodType to be queried in Resolver
const resolvers = {
Query: {
getFoodType: (_, args) => {
const { foodType } = args
...
},
},
}
Then use foodType when querying
Eatery.find({ foodType })
Finally need to return the result
new Promise((resolve, reject) => {
return Eatery.find({ foodType })
.populate()
.exec((err, res) => {
err ? reject(err) : resolve(res)
})
})
Complete example
const resolvers = {
Query: {
getFoodType: (_, args) => {
const { foodType } = args
return new Promise((resolve, reject) => {
return Eatery.find({ foodType })
.populate()
.exec((err, res) => {
err ? reject(err) : resolve(res)
})
})
},
},
}
Use the async/await
const resolvers = {
Query: {
getFoodType: async (_, { foodType }) => {
try {
const eaterys = await Eatery.find({ foodType }).populate()
return eaterys
} catch (e) {
// Handling errors
}
},
},
}

Related

Console output in Mongoose promise not working

I am just working on an analysis project. I have a create method in node but I don't know why suddenly this is happening. I have connected to the database successfully. and wrote created a mongoose model successfully.Now in below code promise.then() is not visited. document is not created. but if I removed any required field, it throws a error as expected.
my create method:
create: function (doc) {
return new Promise((resolve, reject) => {
bcrypt.hash(doc.password, saltRounds).then((hash) => {
doc.password = hash;
console.log(doc); //works
Account.create(doc).then((account) => {
console.log(account); //not working, no error, successful execution, code exit 0.
resolve(account);
}).catch((err) => {
console.log(account); //nothing printed
reject(err);
});
}).catch(err => {
console.log(account); //nothing printed
reject(err);
});
});
}
my database connection in database/db.js
const mongoose = require('mongoose');
require('dotenv').config();
const database = {
connect: function () {
mongoose.connect(
process.env.MONGO_URI + '?retryWrites=true',
{ useNewUrlParser: true, useUnifiedTopology: true }
).then(
function () {
console.log('database connected successfully');
}).catch(error => {
console.log(error);
});
}
};
module.exports = database;
My whole controller code controllers/account.js:
Account = require('../models/account');
const bcrypt = require('bcrypt');
const saltRounds = 10;
authController = {
create: function (doc) {
return new Promise((resolve, reject) => {
bcrypt.hash(doc.password, saltRounds).then((hash) => {
doc.password = hash;
let promise = Account.create(doc);
promise.then((account) => {
console.log(account);
resolve(account);
}).catch((err) => {
console.log(err);
reject(err);
});
}).catch(err => {
console.log(err);
reject(err);
});
});
},
show: function (email) {
return new Promise((resolve, reject) => {
let filter = {email: email};
Account.findOne(filter).then((account) => {
resolve(account);
}).catch((err) => {
reject(err);
});
});
},
update: function (id, update) {
return new Promise((resolve, reject) => {
let filter = {_id: id};
Account.findOneAndUpdate(filter, update).then((account) => {
resolve(account);
}).catch((err) => {
reject(err);
});
});
},
destroy: function (id) {
return new Promise((resolve, reject) => {
let filter = {_id: id};
Account.findOneAndDelete(filter).then(() => {
resolve({deleted: true});
}).catch((err) => {
reject(err);
});
});
},
compare: function (doc) {
return new Promise((resolve, reject) => {
let filter = {email: doc.email};
Account.findOne(filter).then(user => {
bcrypt.compareSync(doc.password, user.password).then((result) => {
resolve(result);
}).catch((err) => {
reject(err);
});
}).catch((err) => {
reject(err);
});
});
}
};
module.exports = authController;
My model for account in models/account.js:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const accountSchema = new Schema({
first: {
type: String,
required: true
},
last: {
type: String,
required: false
},
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
role: {
type: String,
required: true
},
boards: [{
type: mongoose.Schema.Types.ObjectId, ref: 'Board',
required: false
}]
},
{
timestamps: true
});
Account = mongoose.connection.model('User', accountSchema);
module.exports = Account;
my test.js code:
const accountCtrl = require('./controllers/account');
const account = {
first: "User 1",
last: "Last 1",
email: "email1#tasks.com",
password: "password",
role: "test",
};
accountCtrl.create(account).then((result) => {console.log(result)}).catch((err) => {console.log(err)});

DynamoDB: ValidationException: The provided key element does not match the schema

I'm getting the error ValidationException: The provided key element does not match the schema trying to find the field username in my database, when querying the id manually I get a response but with the username I get the error.
const readKey = async (table, queryData, column) => {
const params = {
TableName: table,
Key: {},
}
// { TableName: 'users', Key: { username: 'Maarten' } }
params.Key[column] = queryData
return await new Promise((res, rej) => {
dynamodb.get(params, (err, data) => {
if (err) {
rej(err)
console.log(err)
}
console.log(data)
res(data)
})
})
}
The response:
message: 'The provided key element does not match the schema',
code: 'ValidationException',
time: 2019-11-24T23:50:37.472Z,
requestId: 'RHQF02LFVE7V3NNSGDBF8JR97RVV4KQNSO5AEMVJF66Q9ASUAAJG',
statusCode: 400,
retryable: false,
retryDelay: 14.742327788838905
when I change the params to this:
const params = {
TableName: table,
Key: {
id: '22601770-37ea-47ce-9814-bd979ca4c841',
},
}
I get the response:
{
Item: {
id: '22601770-37ea-47ce-9814-bd979ca4c841',
password: '$2b$10$f/gXRrSCCALPRedCIxOwVuhzi2EX07DeEDVF4h10UuUN.DgYY2Hnq',
username: 'Maarten'
}
}
What am I doing wrong?

How do I fetch a model object by a nested value?

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),
});
},
},

GraphQL: Rootquery returns null [duplicate]

This question already has answers here:
Why does a GraphQL query return null?
(6 answers)
Closed 3 years ago.
I want to have a rootquery that returns every row within my table. But currently when I call that rootquery I only receive null. But one of my rootquery that only returns one row with a specific id does work. So where i am going wrong?
Rootquery's:
This one works
aanvraag:{
type: AanvraagType,
args:{id: {type: GraphQLID}},
resolve(parentValue, args){
const query = `SELECT * FROM aanvraag where id=${args.id}`;
return db.conn.one(query)
.then(data => {
return data;
})
.catch(err => {
return 'Error is: ', err
});
}
},
This one doesn't work
aanvragen:{
type: AanvraagType,
resolve(parentValue, args){
const query = 'SELECT * from aanvraag';
return db.conn.many(query)
.then(data => {
return data;
})
.catch(err => {
return 'Error is: ', err
});
}
}
This is the whole file if someone needs it:
const graphql = require('graphql');
const pgp = require('pg-promise')();
const axios = require('axios');
const db = {}
var cn = {
host: 'localhost', // server name or IP address;
port: 5432,
database: 'admin',
user: 'admin',
password: 'admin123'
};
db.conn = pgp(cn);
const {
GraphQLObjectType,
GraphQLID,
GraphQLString,
GraphQLSchema
} = graphql;
const TeamlidType = new GraphQLObjectType({
name: 'Teamlid',
fields: {
id: { type: GraphQLID },
email: { type: GraphQLString },
naam: { type: GraphQLString }
}
})
const ProjectType = new GraphQLObjectType({
name: 'Project',
fields:{
id: {type: GraphQLID},
naam: { type: GraphQLString },
type: { type: GraphQLString },
lead_naam: { type: GraphQLString },
lead_email: { type: GraphQLString },
teamlid:{
type: TeamlidType,
resolve(parentValue, args){
console.log(parentValue.id);
const query = `SELECT * FROM teamlid WHERE project_id=${parentValue.id}`;
return db.conn.many(query)
.then(data => {
return data;
})
.catch(err => {
return 'The error is', err;
});
}
}
}
})
const AanvraagType = new GraphQLObjectType({
name: 'Aanvraag',
fields:{
id: {type: GraphQLID},
naam: { type: GraphQLString },
email: { type: GraphQLString },
divisie: { type: GraphQLString },
afdeling: { type: GraphQLString },
team: { type: GraphQLString },
project:{
type: ProjectType,
resolve(parentValue, args){
const query = `SELECT * FROM project WHERE aanvraag_id=${parentValue.id}`;
return db.conn.one(query)
.then(data => {
return data;
})
.catch(err => {
return 'The error is', err;
});
}
}
}
})
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
teamlid: {
type: TeamlidType,
args: { id: { type: GraphQLID } },
resolve(parentValue, args) {
const query = `SELECT * FROM teamlid WHERE id=${args.id}`;
return db.conn.one(query)
.then(data => {
return data;
})
.catch(err => {
return 'The error is', err;
});
}
},
aanvraag:{
type: AanvraagType,
args:{id: {type: GraphQLID}},
resolve(parentValue, args){
const query = `SELECT * FROM aanvraag where id=${args.id}`;
return db.conn.one(query)
.then(data => {
return data;
})
.catch(err => {
return 'Error is: ', err
});
}
},
project:{
type: ProjectType,
args:{id: {type: GraphQLID}},
resolve(parentValue, args){
const query = `SELECT * FROM project where id=${args.id}`;
return db.conn.one(query)
.then(data => {
return data;
})
.catch(err => {
return 'Error is: ', err
});
}
},
aanvragen:{
type: AanvraagType,
resolve(parentValue, args){
const query = 'SELECT * from aanvraag';
return db.conn.many(query)
.then(data => {
return data;
})
.catch(err => {
return 'Error is: ', err
});
}
}
}
})
module.exports = new GraphQLSchema({
query: RootQuery,
mutation
})
So I already found my answer. I had to wrap 'aanvraag' in an GraphQLList. So this would work:
aanvragen:{
type: GraphQLList(AanvraagType),
resolve(){
const query = 'SELECT * from aanvraag';
return db.conn.many(query)
.then(data => {
return data;
})
.catch(err => {
return 'Error is: ', err
});
}
}
I am new to GrapQL but i hope this will help someone in the future.

How to architect array of promises in GraphQL resolver with multiple API calls to return a single object type list

I'm stuck in my GraphQL resolver fetching todo-lists for a particular user belonging to a company. According to whether or not they have access to all todo-lists or a certain few, it will fetch for groups the user registered to that have belonging todo-lists, and those should be fetched.
The code so far is capable of logging the requested todo-lists on the query but I have yet to come to the solution on how to actually return data of all of the user's registered groups's todo-lists.
I chose to export the actual logic into a separate function
The Resolver:
allowedListItems: {
type: new GraphQLList(TodoItem),
resolve(parentValue, args) {
return Promise.all([fetchAllowedItems(parentValue._id)]);
}
},
The Promise Function
function fetchAllowedItems(userId) {
return User.findOne({ _id: userId }).then((user) => {
if (user.todoGroups) {
return user.todoGroups.map((groupId) => {
return TodoGroup.findOne({ _id: groupId }).then(group => {
return group.todoLists.map((listId) => {
return TodoList.findOne({ _id: listId })
})
})
})
} else {
return TodoList.find({ company: parentValue.company }).exec();
}
})
}
I am not getting any errors from GraphQL so I guess it's about the way I make the promisses return to the resolver, I'd appreciate a lot if you can help me out!
Update:
I should wrap the maps with a Promise.all, as the mapping returns an array.
Though the updated code brings no improvement in the returned data.
async resolve(parentValue, args) {
let user = await User.findOne({ _id: parentValue._id })
if (user.todoGroups) {
return Promise.all(user.todoGroups.map((groupId) => {
return TodoGroup.findOne({ _id: groupId }).then(group => {
return Promise.all(group.todoLists.map((listId) => {
return TodoList.findOne({ _id: listId });
}))
})
}))
} else {
return TodoList.find({ company: parentValue.company }).exec();
}
}
},
Current query result:
{
"data": {
"user": {
"_id": "5ba11690ad7a93d2b34d21a9",
"allowedTodos": [
{
"_id": null,
"title": null
}
]
}
}
}
You need to call Promise.all on an array of promises, not a promise for that. Also you'll have to call it on each level:
allowedListItems: {
type: new GraphQLList(TodoItem),
resolve(parentValue, args) {
return User.findOne({ _id: parentValue._id }).then(user => {
if (user.todoGroups) {
return Promise.all(user.todoGroups.map(groupId => {
// ^^^^^^^^^^^^
return TodoGroup.findOne({ _id: groupId }).then(group => {
return Promise.all(group.todoLists.map(listId => {
// ^^^^^^^^^^^^
return TodoList.findOne({ _id: listId })
}));
});
}));
} else {
return TodoList.find({ company: parentValue.company }).exec();
}
});
}
}

Categories

Resources