I'm trying to map a json response from mysql query, but i receive ho response: data: NULL
This is my code:
const audience = rows.map((row) => {
db.query(CountAudiences, [row.campaign], function(err, count, fields) {
if (err) throw err;
console.log('Query result: ', count[0].audience);
return {
id: row.id,
title: row.title,
campaign: row.campaign,
action: row.action,
date: row.date,
audiences: count[0].audience
}
});
});
res.json({
count: rows.length,
data: audience
})
Response:
{
"count":1,
"data":[
null
]
}
Do you know how solve this?
Thanks :)
In your code as you are placing a query, so it is a Async hit. Try this
function getResponse(){
let rows = [{ id: 1, title: 5 }, { id: 2, title: "ggg" }]
const audience = rows.map(async (row) => {
return new Promise((resolve,reject)=> {
db.query(CountAudiences, [row.campaign], function (err, count, fields) {
if (err) throw err;
console.log('Query result: ', count[0].audience);
resolve( {
id: row.id,
title: row.title,
campaign: row.campaign,
action: row.action,
date: row.date,
audiences: count[0].audience
})
})
})
});
return Promise.all(audience)
}
getResponse().then((reponseData)=>{
res.json({
count: rows.length,
data: reponseData
})
Related
I want to get the array of rooms and assign it to each property wrt their property_id, but the value returned is a pending promise. Not sure what's wrong. Although when I log the rooms inside the then it does log the value correctly. The result of console.log(property) is given below.
const vendorProfile = catchAsync(async (req, res, next) => {
await passport.authenticate("vendor-jwt", { session: false }, (err, user, info) => {
if (err) {
res.error = err || info.message;
return next(401);
}
if (!user) {
res.error = info.message;
return next(401);
}
return Promise.resolve(
getVendorProfileInfo(user._id)
.then((result) => {
if (result == "error") {
res.error = "Failed to fetch Vendor Profile";
next(500);
}
return getPropertyByVendorId(result._id).then((prop) => {
for (const property of prop) {
property._doc.property_rooms = getAllRooms(property._id).then((rooms) => rooms);
console.log(property);
}
res.message = "Vendor Profile fetched successfully";
res.data = {
vendor_info: result,
vendor_properties: prop,
};
return next(200);
});
})
.catch((err) => {
Logger.error(err);
res.error = "Failed to get vendor profile";
return next(500);
})
).catch((err) => {
Logger.error(err);
res.error = "Failed to get vendor profile";
return next(500);
});
})(req, res, next);
});
This is the function to get all the rooms for that property_id:
const getAllRooms = (propertyId) => {
return Promise.resolve(Room.find({ property_id: propertyId }).then((result) => result)).catch((err) => {
Logger.error(err);
return "error";
});
};
Here is my console.log(property):
{
property_basic_info: {
property_name: 'Welcome',
property_star_rating: 1,
property_booking_since: 2021,
property_channel_manager: ''
},
property_location: {
property_geo_loc: { coordinates: [Array], type: 'Point' },
property_locality: 'bhandup',
property_address: 'MAHAVIR UNIVERSE',
property_country: 'India',
property_state: 'Maharashtra',
property_city: 'Mumbai',
property_zip_code: '400078'
},
property_contact_details: { phone_no: '7059462868', email: 'roy.srijan#outlook.com' },
property_amenities: {
basic_facilities: [ 'Electricity', 'Air Conditioning', 'Elevator/ Lift', 'Bathroom' ],
general_services: [ 'Food', 'Bellboy service' ],
outdoor_activities_sports: [],
common_area: [],
food_drink: [],
health_wellness: [],
business_center_conference: [],
beauty_spa: [],
security: []
},
property_policies: {
checkin_time: '10:06',
checkout_time: '22:06',
cancellation_policy: 'Free cancellation upto 48 hrs'
},
property_rules: {
id_proof: {
acceptable_identity_proofs: 'Adhaar',
unacceptable_identity_proofs: 'Adhaar',
allow_same_id: true
},
guest_profile: [
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object]
],
general_safety_hygiene_guidelines: [],
room_safety_hygiene: [],
social_distancing: [],
food_drinks_hygiene: [],
property_restrictions: [],
pet_policy: [],
guest_suitabilty: [],
checkin_checkout_policy: [],
extra_bed_policy: [ [Object] ],
custom_policy: []
},
property_finance_legal: { gst_details: '29AAACR4849R2ZG' },
property_status: 1,
property_photo_id: [],
_id: 61607791b1af193c7b8b9f08,
vendor_id: 61607775b1af193c7b8b9f07,
createdAt: 2021-10-08T16:53:37.734Z,
updatedAt: 2021-10-08T16:53:37.734Z,
__v: 0,
property_rooms: Promise { <pending> }
}
Thanks in advance.
That's because you are logging the promise outside the then method.
The promise is resolved async so outside then it is not resolved yet.
you have to change this line:
property._doc.property_rooms = getAllRooms(property._id).then((rooms) => rooms);
console.log(property);
to
property._doc.property_rooms = getAllRooms(property._id).then((rooms) => console.log(rooms));
or use async/await to work with it like sync values
UPDATE
I have a mongoose schema and express controller, now I have to post an Array of Objects based on that schema, I have to post like 30 Objets, here is an example of two I posted and I received that response, and I wanto to see the Array of all Objects.
CoursesModel.ts
const CoursesSchema = new Schema({
courses: [{
course_status: String,
course_code: String,
course_name: req.body.course_name,
institute_name: String,
hour_duration: Number,
modality: String,
schedule: String,
start_date: Date,
finish_date: Date,
enroll_date_limit: Date,
course_value: Number,
}],
created_at: {
type: Date,
default: Date.now
}
});
coursesController.ts // createCourse
const Courses = CoursesModel;
public createCourses(req: Request, res: Response) {
try {
if (!req.body) {
throw new Error(`Is missing parameter : Table data`);
}
const createCourse = {
courses: [{
course_status: req.body.course_status,
course_code: req.body.course_code,
course_name: req.body.course_name,
institute_name: req.body.institute_name,
hour_duration: req.body.hour_duration,
modality: req.body.modality,
schedule: req.body.schedule,
start_date: req.body.start_date,
finish_date: req.body.finish_date,
enroll_date_limit: req.body.enroll_date_limit,
course_value: req.body.course_value,
}],
created_at: new Date()
};
let newCourses = new Courses(createCourse);
newCourses.save().then(data => {
res.json(data);
})
.catch(err => {
res.status(500).send({
message:
err.message || "Some error occurred while creating the course"
});
})
);
} catch (error) {
this.logger.error({
data: req.body,
error: error,
source: 'Error in function createCourses'
});
res.status(500);
return res.send({ error: (error.message) ? error.message : "Internal server error" });
}
}
Json body I post on Insomnia
{"courses":[{
"course_status": "Active",
"course_code": "0004",
"institute_name": "Berkley",
"course_name": "Programming",
"month_duration": 2,
"hour_duration": 120,
"modality": "Virtual",
"schedule": "2 a 5",
"start_date": "2021-07-02T05:00:16.000Z",
"finish_date": "2021-07-02T05:00:16.000Z",
"enroll_date_limit": "2021-07-02T05:00:16.000Z",
"course_value": 300000,
},
{
"course_status": "Active",
"course_code": "0005",
"institute_name": "MIT",
"course_name": "Digital Marketing",
"hour_duration": 120,
"modality": "Virtual",
"schedule": "2 a 5",
"start_date": "2021-07-02T05:00:16.000Z",
"finish_date": "2021-07-02T05:00:16.000Z",
"enroll_date_limit": "2021-07-02T05:00:16.000Z",
"course_value": 300000,
}]}
This is what I get from Insomnia
Insomnia response
{
"successfully": true,
"data": {
"_id": "5f1ae0e3cf5d702706b5bb09",
"courses": [
{
"_id": "5f1ae0e3cf5d702706b5bb0a"
}
],
"created_at": "2020-07-24T13:23:47.173Z",
"__v": 0
}
}
I solve in this way
const Courses = CoursesModel;
public async createCourses(req: Request, res: Response) {
try {
if (!req.body) {
throw new Error(`Is missing parameter : Table data`);
}
const courses = []
for(const course of req.body.courses){
const tableCourse ={
course_status: course.course_status,
course_code: course.course_code,
course_name: course.course_name,
institute_name: course.institute_name,
hour_duration: course.hour_duration,
modality: course.modality,
schedule: course.schedule,
start_date: course.start_date,
finish_date: course.finish_date,
enroll_date_limit: course.enroll_date_limit,
course_value: course.course_value,
created_at: new Date()
};
let newCourses = new Courses(tableCourse);
const newCourses = await newTableCourses.save()
courses.push(newCourses)
}
res.json({ successfully: true, data: { courses } });
} catch (error) {
this.logger.error({
data: req.body,
error: error,
source: 'Some error occurred while creating the course.'
});
res.status(500);
return res.send({ error: (error.message) ? error.message : "Internal server error" });
}
}
CourseModel.ts
const CoursesSchema = new Schema({
course_status: String,
course_code: String,
course_name: req.body.course_name,
institute_name: String,
hour_duration: Number,
modality: String,
schedule: String,
start_date: Date,
finish_date: Date,
enroll_date_limit: Date,
course_value: Number,
created_at: {
type: Date,
default: Date.now
}
});
Use res.json(data) instead of res.send(data) and instead of return from directly use save
const Courses = CoursesModel;
public createCourses(req: Request, res: Response) {
try {
if (!req.body) {
throw new Error(`Is missing parameter : Table data`);
}
const createCourse =Courses ({
courses: [{
course_status: req.body.course_status,
course_code: req.body.course_code,
course_name: req.body.course_name,
institute_name: req.body.institute_name,
hour_duration: req.body.hour_duration,
modality: req.body.modality,
schedule: req.body.schedule,
start_date: req.body.start_date,
finish_date: req.body.finish_date,
enroll_date_limit: req.body.enroll_date_limit,
course_value: req.body.course_value,
}],
created_at: new Date()
});
newCourses.save().then(data => {
res.json(data);
})
.catch(err => {
res.status(500).send({
message:
err.message || "Some error occurred while creating the course"
});
})
);
} catch (error) {
this.logger.error({
data: req.body,
error: error,
source: 'Error in function createCourses'
});
res.status(500);
return res.send({ error: (error.message) ? error.message : "Internal server error" });
}
}
I have and map structure stored at dynamodb, an I would like to add another attribute inside school object
something like:
{
name: 'Felipe'
uid: 112233,
data: {
structure: {
school: {
name: 'beta'
}
}
}
}
previously the add_year did not was a part of the structure, so this part is new
school: {
name: 'beta'
add_year: '2020'
}
How can I accomplised that?
I've tried the following solutions, without success
(async ()=>{
try {
let teste = await dynamoDb.updateItem({
TableName: 'test',
Key: {
uid: "112233"
},
UpdateExpression: "SET data.#structure.#school = list_append(#structure, :attrValue)",
ExpressionAttributeNames: {
"#data": "data",
"#structure": "structure",
"#school": "school",
},
ExpressionAttributeValues: {
":school":{
"add_year": 2020
}
},
ReturnValues:"UPDATED_NEW "
})
console.log('update',teste)
} catch (error) {
console.log(error)
}
Felipe, did you see the AWS documentation about this topic?
I think this code can work for you:
(async () => {
try {
var params = {
TableName: 'test',
Key: {
"uid": "112233"
},
UpdateExpression: "SET data.structure.school.add_year = :year)",
ExpressionAttributeValues: {
":add_year": 2020
},
ReturnValues: "UPDATED_NEW"
}
dynamoDb.update(params, (err, data) => {
if (err) {
console.error("Unable to update item. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("UpdateItem succeeded:", JSON.stringify(data, null, 2));
}
})
} catch (error) {
console.log(error)
}
})
const { DocumentClient } = require('aws-sdk/clients/dynamodb');
const documentClient = new DocumentClient({
region: 'us-east-1',
});
try {
let add_year= '2020'
let teste = documentClient.update({
TableName: 'test',
Key: {
uid: "112233"
},
UpdateExpression: `SET #data.structure.school= :add_year`,
ExpressionAttributeValues: {
':add_year': add_year
},
ExpressionAttributeNames: {
"#data": "data"
},
ReturnValues:"ALL_NEW"
}).promise()
teste.then(t => console.log(t));
} catch (error) {
console.log(error)
}
I'm combining a GraphQL app with my existing Firebase project and am having a lot of problems getting the queries to correctly get data from the firestore().
So far I have the mutations working correctly, but when I go to query the data I can't get the firestore().get() snapshot into a form that graphQL will recognize.
so far it looks like this:
const {GraphQLObjectType,
GraphQLString,
GraphQLBoolean,
GraphQLFloat,
GraphQLSchema,
GraphQLID,
GraphQLList,
GraphQLNonNull} = require("graphql");
const admin = require('firebase-admin');
const functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);
//Models
const Room = admin.firestore().collection('room');
const Position = admin.firestore().collection('position');
const Plant = admin.firestore().collection('plant');
const PlantInfo = admin.firestore().collection('plantInfo');
const RoomType = new GraphQLObjectType({
name: "Room",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
description: { type: GraphQLString },
floor: { type: GraphQLString },
building: { type: GraphQLString },
positions: {
type: new GraphQLList(PositionType),
resolve(parent, arg) {
//return _.filter(positions, {inRoomId:parent.id})
return Position.orderByChild('inRoomId').equalTo(parent.id);
}
}
})
});
const PositionType = new GraphQLObjectType({
name: "Position",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
description: { type: GraphQLString },
exposure: { type: GraphQLString },
size: { type: GraphQLString },
inRoom: {
type: RoomType,
resolve(parent, args) {
//return _.find(rooms, {id:parent.inRoomId})
return Room.child(parent.inRoomId);
}
}
})
});
const RootQuery = new GraphQLObjectType({
name: "RootQueryType",
fields: {
room: {
type: RoomType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
//code to get data from db/othersourse
//return _.find(rooms, {id: args.id});
return Room.child(args.id);
}
},
position: {
type: PositionType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
//code to get data from db/othersourse
//return _.find(positions, {id: args.id})
return Position.child(args.id);
}
},
rooms: {
type: new GraphQLList(RoomType),
resolve(parent, args) {
//return rooms
return Room.get().then(snapshot => {snapshot.forEach(doc => {return doc})})
}
},
positions: {
type: new GraphQLList(PositionType),
resolve(parent, args) {
//return positions
return Position.get().then(doc => console.log(doc)).catch(err => console.log('Error getting document', err));
}
}
}
});
const Mutation = new GraphQLObjectType({
name: "Mutation",
fields: {
addRoom: {
type: RoomType,
args: {
name: { type: new GraphQLNonNull(GraphQLString) },
floor: { type: new GraphQLNonNull(GraphQLString) },
building: { type: new GraphQLNonNull(GraphQLString) }
},
resolve(parent, args) {
let room = {
name: args.name,
floor: args.floor,
building: args.building
};
return Room.add(room);
}
},
addPosition: {
type: PositionType,
args: {
name: { type: new GraphQLNonNull(GraphQLString) },
exposure: { type: new GraphQLNonNull(GraphQLString) },
size: { type: new GraphQLNonNull(GraphQLString) },
inRoomId: { type: new GraphQLNonNull(GraphQLString) }
},
resolve(parent, args) {
let position = {
name: args.name,
exposure: args.exposure,
size: args.size,
inRoomId: args.inRoomId
};
return Position.add(position);
}
}
}
});
module.exports = new GraphQLSchema({
query: RootQuery,
mutation: Mutation
});
Under the RootQuery -> Rooms I'm trying to get a graphQL query to return all the rooms in my 'room' collection. I have been able to get it to console.log() a list of documents using:
return Room.get()
.then(snapshot => {
snapshot.forEach(doc => {
console.log(doc.id, " => ", doc.data());
But getting this into an array has so far eluded me. Any help is really appreciated.
Seeing as no one was able to answer this, I ended up figuring it out for myself :p
So resolve functions relating to getting a collection of related data for example positions. the following works:
first you need a function to convert the snapshots into an array as this is what graphQL is expecting. This also allows your to seperate the id and add it in with the array item:
const snapshotToArray = (snapshot) => {
var returnArr = [];
snapshot.forEach((childSnapshot)=> {
var item = childSnapshot.data();
item.id = childSnapshot.id;
returnArr.push(item);
});
return returnArr;
};
Next when getting the data you use .get() which returns a promise (and error) which can be passed into the snapshotToArray().
return Position.get().then((snapshot) => {
return snapshotToArray(snapshot);
})
For resolve functions that only call on one dataset for example inRoom. Its similar to the first one except using .where() and seperating the id and data() in the snapshot functions:
return Room.doc(parent.inRoomId).get().then((snapshot) => {
var item = snapshot.data();
item.id = snapshot.id;
return item;
})
Just incase someone else runs into the same problem :)
I'm creating a Reddit clone and I'm setting up the backend first, but having trouble creating relational data.
When I use this query:
query {
subreddit(id: 1) {
name
posts {
title
}
}
}
I expect:
{
"data": {
"subreddit": {
"name": "javascript"
"posts": [
{
"title": "JS Post"
}
]
}
}
}
What I get:
{
"data": null,
"errors": [
{
"message": "Cannot return null for non-nullable field Subreddit.posts.",
"locations": [
{
"line": 4,
"column": 5
}
],
"path": [
"subreddit",
"posts"
]
}
]
}
Here's the schema:
type Query {
subreddits: [Subreddit!]!
subreddit(id: ID!): Subreddit!
posts: [Post!]!
post(id: ID!): Post!
}
type Mutation {
createSubreddit(
name: String!
description: String!
contentType: String!
ageRestriction: Boolean!
): Subreddit!
}
type Subreddit {
id: ID!
name: String!
description: String!
contentType: String!
ageRestriction: Boolean!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
body: String!
subredditId: ID!
# userId: ID!
}
Here is server/index.js:
const { GraphQLServer } = require('graphql-yoga');
let dummySubreddits = [
{
name: 'javascript',
description: 'all things javascript',
contentType: 'any',
ageRestriction: false,
id: 1
},
{
name: 'react',
description: 'all things react',
contentType: 'any',
ageRestriction: false,
id: 2
},
{
name: 'primsa',
description: 'all things prisma',
contentType: 'any',
ageRestriction: false,
id: 3
}
];
let idCountSubreddit = dummySubreddits.length;
let dummyPosts = [
{ title: 'JS Post', body: 'Body of post one', id: 1, subredditId: 1 },
{ title: 'React Post', body: 'Body of post two', id: 2, subredditId: 2 },
{
title: 'Prisma Post',
body: 'Body of post three',
id: 3,
subredditId: 3
}
];
let idCountPost = dummyPosts.length;
const resolvers = {
Query: {
subreddits: () => dummySubreddits,
subreddit: (parent, args) => {
return dummySubreddits.find(obj => obj.id == args.id);
},
posts: () => (parent, args) => {
return dummyPosts.find(obj => obj.subredditId == parent.id);
},
post: (parent, args) => {
return dummyPosts.find(obj => obj.id == args.id);
}
},
Mutation: {
createSubreddit: (parent, args) => {
let subreddit = {
id: idCountSubreddit++,
name: args.name,
description: args.description,
contentType: args.contentType,
ageRestriction: args.ageRestriction
};
return subreddit;
}
}
};
const server = new GraphQLServer({ typeDefs: './schema.graphql', resolvers });
server.start(() => console.log('Server is running on localhost:4000'));
I'm using the GraphQL desktop app for querying and I do not have grapql-yoga config file.
Where am I going wrong? I'd like to be pointed in the right direction so I can figure it out myself. This is my first time working with GraphQL alone, after doing some tutorials on YouTube, however they used graphql-express and I'm using graphql-yoga.
Move the resolver you have written for Query's posts into Subreddit to resolve the posts field there. If your resolver does not comply to the default resolver implementation:
(parent) => parent[fieldName]
Like in your case
(parent) => parent.posts
You have to specify it yourself. If your field posts on Query should display all the posts you might want to go for the following implementations:
const resolvers = {
Query: {
subreddits: () => dummySubreddits,
subreddit: (parent, args) => {
return dummySubreddits.find(obj => obj.id == args.id);
},
posts: () => dummyPosts,
post: (parent, args) => {
return dummyPosts.find(obj => obj.id == args.id);
}
},
Subreddit: {
posts: () => (parent, args) =>
dummyPosts.filter(obj => obj.subredditId == parent.id),
},
Mutation: {
createSubreddit: (parent, args) => {
let subreddit = {
id: idCountSubreddit++,
name: args.name,
description: args.description,
contentType: args.contentType,
ageRestriction: args.ageRestriction
};
return subreddit;
}
}
};
I had to add a resolver for subreddit to deal with posts.
const resolvers = {
Query: {
subreddits: () => dummySubreddits,
subreddit: (parent, args) => {
return dummySubreddits.find(obj => obj.id == args.id);
},
posts: (parent, args) => {
return dummyPosts;
},
post: (parent, args) => {
return dummyPosts.find(obj => obj.id == args.id);
}
},
Mutation: {
createSubreddit: (parent, args) => {
let subreddit = {
id: idCountSubreddit++,
name: args.name,
description: args.description,
contentType: args.contentType,
ageRestriction: args.ageRestriction
};
return subreddit;
}
},
// This resolver was needed
Subreddit: {
posts: subreddit =>
dummyPosts.filter(obj => obj.subredditId == subreddit.id)
}
};