So I'm working on a graphql server and I'm trying to make an async/await external call to facebook's server.
The issue is that all this information does come back but it does not save to the db.
How do I know it does come back? if I use findOne instead of findOneAndUpdate I can console.log all the info and see it successfully but once I switch back I don't even get an error.
I have looked at the mongoose docs and tried to apply the findOneAndUpdate properly but it just laughs at me no error it just doesn't do anything.
Any way here is my code if any one can give me some advice it would really be appreciated.
The first set is code using findOne which I know works 100% but does not save or update the doc.
The second one is when I try to do it with FindOneAndUpdate.
getFacebookPageID: {
type: FacebookType,
description: 'Gets all the content we want from facebook once a user has granted permissions',
args: {
id: { type: GraphQLString },
accessToken: { type: GraphQLString },
facebook: { type: InputFacebookType }
},
resolve: (parent, args) => User.findOne({ _id: args.id }, async (err, docs) => {
console.log('next step is getcontent');
// const clientId = process.env.FACEBOOK_ID;
// const reDirectFBUri = process.env.FACEBOOK_ID_URI;
const { accessToken } = docs.tokens.find((item) => item.kind === 'facebook');
const userId = docs.facebookId;
console.log(userId);
const getFBaccounts = `https://graph.facebook.com/${userId}/accounts?access_token=${accessToken}`;
let pages = null;
await axios.get(getFBaccounts)
.then((response) => {
pages = response.data.data;
// this above line is all the fb pages user has give us access to
console.log('pages', response.data.data);
const query = { _id: args.id, };
console.log('This should be object id', query);
User.updateOne(query, {
pages,
}, (err, docs) => {
console.log('Any errors here are problems with saving!', err, docs);
});
})
.catch((err) => console.log(err));
return FacebookType;
}
),
},
I have also tried this below and that simply will not even console log anything. This is me trying to use findOneAndUpdate
getFacebookPageID: {
type: FacebookType,
description: 'Gets all the content we want from facebook once a user has granted permissions',
args: {
id: { type: GraphQLString },
accessToken: { type: GraphQLString },
facebook: { type: InputFacebookType }
},
resolve: (parent, args) => User.findOneAndUpdate({ _id: args.id },{ pages: async (err, docs) => {
console.log('next step is getcontent');
const { accessToken } = docs.tokens.find((item) => item.kind === 'facebook');
const userId = docs.facebookId;
console.log(userId);
const getFBaccounts = `https://graph.facebook.com/${userId}/accounts?access_token=${accessToken}`;
let pages = null;
await axios.get(getFBaccounts)
.then((response) => {
pages = response.data.data;
console.log('pages', response.data.data);
})
.catch((err) => console.log(err));
return FacebookType;
}
},
{new: true}
),
},
you use async/await in mix with promises. You should choose one approach (I suggest async/await);
resolve: async (parent, args) => {
try {
//get user
const user = await User.findById(args.id); //user is mongooose instance - https://mongoosejs.com/docs/api.html#document_Document-save
const { accessToken } = user.tokens.find((item) => item.kind === 'facebook');
const userId = user.facebookId;
const getFBaccounts = `https://graph.facebook.com/${userId}/accounts?access_token=${accessToken}`;
//get pages
const fbResponse = await axios.get(getFBaccounts);
//use mongoose prototype method "save" to update the user
user.pages = fbResponse.data.data;
await user.save();
return user;
} catch(e) {
console.log(e);
}
}
Related
can this be done with fetch api which method should i use post or put? please reply.. can someone please give me the complete api to push orderSchema as a subdocument in userSchema i have scrolled tons and tons of links still i am not able to find any answer too this
this is the schema i am using in mongo db.
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)
I am using this api to save userschema and this is working.
import initDB from '../../helper/initDB';
import User from '../../models/addUser';
initDB()
export default async (req, res) => {
(req.method)
{
"POST"
await handler(req, res)
}
}
const handler = async (req, res) => {
if (req.method == 'POST') {
console.log(req.body)
const { name,phone,address } = req.body
let u = new User( {name,phone,address } )
await u.save()
res.status(200).json({ success: "success" })
}
else {
res.status(400).json({ error: "this method is not required" })
}
}
I am using this api to save this data as a subdocument but this api is not working what changes should i make?
import initDB from '../../../helper/initDB';
import User from '../../../models/addUser';
initDB()
export default async (req, res) => {
(req.method)
{
"POST"
await handler(req, res)
}
}
const handler = async (req, res) => {
if (req.method == 'POST') {
console.log(req.body)
const { uid } = req.query
const user = await User.findOne({ _id: uid })
const { rsph, rcyl, raxis, lsph, lcyl, laxis, add, frame, lens } = req.body
const order = ({ rsph, rcyl, raxis, lsph, lcyl, laxis, add, frame, lens });
user.orders.push(order);
await user.save()
res.status(200).json({ success: "success" })
}
else {
res.status(400).json({ error: "this method is not required" })
}
}
please reply...
Remove bracket () from the below line.
const order = ({ rsph, rcyl, raxis, lsph, lcyl, laxis, add, frame, lens });
only pass the object, as
const order = { rsph, rcyl, raxis, lsph, lcyl, laxis, add, frame, lens };
The final should be as:
const handler = async (req, res) => {
if (req.method == 'POST') {
console.log(req.body)
const { uid } = req.query
const user = await User.findOne({ _id: uid })
const { rsph, rcyl, raxis, lsph, lcyl, laxis, add, frame, lens } = req.body
const order = { rsph, rcyl, raxis, lsph, lcyl, laxis, add, frame, lens };
user.orders.push(order);
await user.save()
res.status(200).json({ success: "success" })
}
else {
res.status(400).json({ error: "this method is not required" })
}
}
im trying to write a function that updates shopping cart which given products info and give user the updated shopping cart, however when I call this function, database is updating but response is not.
Code
export const addToCart: Hapi.Lifecycle.Method = async (request, h, err) => {
const payload: ProductIdPayload = <ProductIdPayload>request.payload;
const userId: string = <string>request.auth.credentials._id;
try {
const [shoppingCart, product] = await Promise.all([
ShoppingCartModel.findOne({ userId: userId }),
ProductModel.findById(payload.productId),
]);
if (product) {
console.log(product);
if (shoppingCart) {
await shoppingCart.updateOne({
$push: { productIds: payload.productId },
$inc: { totalValue: product.price },
});
//above line updates database but below command returns non-updated shopping cart
return h.response({
shoppingCart: shoppingCart,
});
} else {
const newShoppingCart = new ShoppingCartModel({
userId: userId,
productIds: [payload.productId],
totalValue: product.price,
});
console.log(newShoppingCart)
await newShoppingCart.save();
return h.response({ shoppingCart: newShoppingCart });
}
} else {
const error = Boom.notFound("Product Not Found");
return error;
}
} catch (error) {
throw new Error();
}
};
Any idea why is this happening?
Try using:
const updatedShoppingCart = await shoppingCart.updateOne({
$push: { productIds: payload.productId },
$inc: { totalValue: product.price },
});
return h.response({
shoppingCart: updatedShoppingCart,
});
If the above solution doesn't work for you use findOneAndUpdate function on the Model and pass {new: true} in the options.
I want to update a particular user's financial records which is an array.
<-- This is my user model -->
const FinanceSchema = new mongoose.Schema({
moneyToBePaid: {
type: Number,
},
moneyPaid: {
type: Number,
},
moneyToBeReceived: {
type: Number,
},
moneyReceived: {
type: Number,
},
});
const UserSchema = new mongoose.Schema({
financialInformation: [FinanceSchema],
});
module.exports = mongoose.model("user", UserSchema);
<-- This is my post route -->
router.post("/users/:id/profile", async (req, res) => {
const _id = req.params.id;
const {
moneyToBePaid,
moneyPaid,
moneyToBeReceived,
moneyReceived,
} = req.body;
const finance = {
moneyToBePaid,
moneyPaid,
moneyToBeReceived,
moneyReceived,
};
try {
const user = await User.findById(_id);
user.financialInformation.push(finance);
await user.save();
res.status(200).json(user);
}
<-- This is my update route -->
router.patch("/users/:user_id/profile/:profile_id", async (req, res) => {
const user_id=req.params.user_id;
const profile_id=req.params.profile_id;
try {
}
I am confused how to update a particular user's particular finance record.
Assuming you want to update the moneyPaid property of specific finance array element:
try {
const user_id=req.params.user_id;
const profile_id=req.params.profile_id;
await User.findOneAndUpdate(
{ "_id": user_id, "financialInformation._id": profile_id },
{
"$set": {
"financialInformation.$.moneyPaid": "2258" // the data you want to update
}
});
res.status(200).send('user updated');
} catch(err) {
console.log(err);
res.send(err);
}
When I create a new instance of my User with Sequelize, I get the full object returned from the database as a response to the Create. I'm trying to prevent Sequelize from returning the hashed password stored in my User table on create.
exports.create = (payload, err, success) => {
db.user.create(payload).then(success).catch(err);
console.log('Created new user record.');
};
I tried using the exclude property, but the full object returns.
exports.create = (payload, err, success) => {
db.user.create(payload, {
attributes: {
exclude: ['password']
}
}).then(success).catch(err);
console.log('Created new user record.');
};
I am able to use the exclude property in attributes on my find and findAll routes like the example below, but I haven't been able to get it to work with my create.
exports.find = (payload, err, success) => {
db.user.find({
where: {
id: payload.id,
},
attributes: {
exclude: ['password']
}
}).then(success).catch(err);
console.log('Retrieved user record with id: ' + payload.id);
};
You can try using toJSON instance method to exclude attributes:
Model:
instanceMethods: {
toJSON: function () {
const userObj = Object.assign({}, this.dataValues);
delete userObj.password;
return userObj
}
}
Route file:
user.create(request.body, (err) => {
res.status(500).json(err);
console.log('Error creating new user.');
}, (data) => {
res.status(200).json(data.toJSON());
console.log('User created.');
});
Use Getter on your model and return undefined
password: {
type: DataTypes.STRING,
get() {
return undefined;
}
}
I am following this graphql tutorial, everything was going ok until I try to use dataloaders.
My server.js is:
const start = async () => {
const mongo = await connectMongo();
const buildOptions = async req => {
const user = await authenticate(req, mongo.Users);
return {
context: {
dataloaders: buildDataloaders(mongo),
mongo,
user
},
schema
};
};
app.use('/graphql', bodyParser.json(), graphqlExpress(buildOptions));
app.use(
'/graphiql',
graphiqlExpress({
endpointURL: '/graphql',
passHeader: `'Authorization': 'bearer token-name#email.com'`
})
);
app.use('/', expressStaticGzip('dist'));
app.use('/attendance', expressStaticGzip('dist'));
app.use('/login', expressStaticGzip('dist'));
spdy.createServer(sslOptions, app).listen(process.env.PORT || 8080, error => {
if (error) {
console.error(error);
return process.exit(1);
} else {
console.info(
`App available at https://localhost:${process.env.PORT || 3000}`
);
}
});
};
My copy and paste dataloaders.js:
const DataLoader = require('dataloader');
async function batchUsers(Users, keys) {
return await Users.find({ _id: { $in: keys } }).toArray();
}
module.exports = ({ Users }) => ({
userLoader: new DataLoader(keys => batchUsers(Users, keys), {
cacheKeyFn: key => key.toString()
})
});
And my resolvers.js:
export default {
Query: {
allLinks: async (root, data, { mongo: { Links } }) =>
Links.find({}).toArray()
},
Mutation: {
createLink: async (root, data, { mongo: { Links }, user }) => {
const newLink = Object.assign({ postedById: user && user._id }, data);
const response = await Links.insert(newLink);
return Object.assign({ id: response.insertedIds[0] }, newLink);
},
createUser: async (root, data, { mongo: { Users } }) => {
const newUser = {
name: data.name,
email: data.authProvider.email.email,
password: data.authProvider.email.password
};
const response = await Users.insert(newUser);
return Object.assign({ id: response.insertedIds[0] }, newUser);
},
signinUser: async (root, data, { mongo: { Users } }) => {
const user = await Users.findOne({ email: data.email.email });
if (data.email.password === user.password) {
return { token: `token-${user.email}`, user };
}
}
},
Link: {
id: root => root._id || root.id,
postedBy: async ({ postedById }, data, { dataloaders: { userLoader } }) => {
return await userLoader.load(postedById);
}
},
User: {
id: root => root._id || root.id
}
};
When I try get my allLinks I got the error:
TypeError: The loader.load() function must be called with a value,but
got: undefined.
Can anyone help me?
So I was able to reproduce the error by creating a link with a user, deleting the user from the Mongo database, and then querying for the postedBy attribute of the Link.
I would suggest dropping all your links and recreating your user (register + sign in), creating a new link, then querying for the postedBy field.