How to push an object into an array with GraphQL? - javascript

I would like to change the way my resolver is creating the payment cards in my DB. So now I create the wallet in one collection then a payment in another collection and use the wallet_id to in my payment to link them. But now I want to push the payments into a cards[] that is defined in wallet. Any idea how to do that in resolver?
This is my Wallet schema
const WalletSchema = new Schema({
tokens: {
type: Number,
default: 0
},
userId: {
type: Schema.Types.ObjectId,
ref: 'User',
unique: true
},
cards: [
{
type: Schema.Types.ObjectId,
ref: 'Payment'
}
]
}, { timestamps: true });
and this is my createPayment resolver
createPayment: async (_, { wallet_id, ...args }, { user }) => {
try {
await requireAuth(user);
const payment = await Payment.create({ ...args, wallet: wallet_id });
pubsub.publish(PAYMENT_ADDED, { [PAYMENT_ADDED]: payment });
return payment;
} catch (error) {
throw error;
}
},
Any idea?

You need to create another Schema for card payments;
const WalletSchema = new Schema({
tokens: {
type: Number,
default: 0
},
userId: {
type: Schema.Types.ObjectId,
ref: 'User',
unique: true
},
cards: [ PaymentSchema ] <-- here
}, { timestamps: true });
// new schema
const PaymentSchema = new Schema({
type: Schema.Types.ObjectId,
ref: 'Payment'
});
Based on Wallet schema you need to write expose graphql schema

Related

How to save an array of strings in mongodb

I have found a few similar questions on stack overflow like this one:
How to save array of Strings in Node Mongodb
Mongoose - Save array of strings
but I cant figure out why my method is not working
I am trying to save the string of arrays "jobType".
context: I am creating an app where people can post jobs.
each job can have multiple types.
here is my job model::
const mongoose = require("mongoose");
const postSchema = mongoose.Schema({
content: { type: String, required: true },
imagePath: { type: String, required: true },
state: { type: String, required: true },
substate: { type: String, required: true },
address: { type: String, required: true },
jobType: { type: [String] },
creator: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true }
});
module.exports = mongoose.model("Job", postSchema);
this is the API used to save the data on MongoDB:
I am 100% sure that the data is getting to the API correctly.
the parameter "req.body.jobtype" contains all the info as a string.
I am trying to use JSON.parse to change the string into an array but its not working.
when I check MongoDB, an empty array is being stored
const Job = require("../models/job");
exports.createJob = (req, res, next) => {
console.log('create job api hit')
const url = req.protocol + "://" + req.get("host");
const post = new Job({
content: req.body.content,
imagePath: url + "/images/" + req.file.filename,
creator: req.userData.userId,
state: 'new',
substate: 'new',
address: req.body.address,
jobtype: JSON.parse(req.body.jobtype) // fix: not storing correctly
});
post
.save()
.then(createdJob => {
res.status(201).json({
message: "Job added successfully",
post: {
...createdJob,
'pecker':'pecker hecks out',
id: createdJob._id
}
});
})
.catch(error => {
res.status(500).json({
message: JSON.stringify(error)
});
});
};
You have a typo. In your model, you defined jobType property, but when saving the data, you are passing it as jobtype.
So, instead of this:
jobtype: JSON.parse(req.body.jobtype)
Do this:
jobType: JSON.parse(req.body.jobtype)

Mongoose filter by nested reference

I have 3 mongoose schemas Employee, Team and Project. Employee has reference to the team and Team has reference to the Project. Is it possible to get all employees by project Id? I don't want to change schema or use Team model with populate.
const employeeSchema = mongoose.Schema({
email: { type: String, required: true, unique: true },
team: { type: mongoose.Schema.Types.ObjectId, ref: "Team" },
});
const teamSchema = mongoose.Schema({
name: { type: String, required: true },
employees: [{ type: mongoose.Schema.Types.ObjectId, ref: "User" }],
project: { type: mongoose.Schema.Types.ObjectId, ref: "Project" },
});
Below code throws cast error, id is a valid project id.
router.get("/:id/employees", checkAuth, (req, res, next) => {
const id = req.params.id;
console.log(id);
Employee.find({ team:{project:id}}).then((employees) => {
console.log(employees);
});
});
Yes it is possible to get all employees using project Id.but not using single query so you have to modify your function like this
const id = mongoose.Types.ObjectId(req.params.id);
Team.findOne({ project: id }, { _id: 1 }, function (err, docs) {
// Get the Team which match with project ID
Employee.find({ team: docs._id }, function (err, docs1) {
//Get all employee belongs to that team and project
console.log(docs1);
});
});

Issue while displaying fields of docs in MongoDB

I am new to programming and trying my best but without any help I don't think I am able to find it ;)
I want to display all products from mongoDB by brand. I already have route for category but in the same time when I am trying to implement the same strategy to brands I have 404 not found.
my code :
router.get('/:categorySlug', (req, res, next) => {
let filter = {};
if(req.query.hasOwnProperty("filter")){
filter['price'] = req.query.price
}
const slug = req.params.categorySlug;
Category.findOne({slug: slug})
.select('_id')
.exec()
.then(category => {
if(category){
if(category.parent === ""){
Product.find({category: category._id})
.select('_id name price productPic category brand slug')
.sort(filter)
.exec()
.then(products => {
res.status(200).json({
message: products
})
})
.catch(error => {
return res.status(404).json({
message: error
})
})
}
}else{
return res.status(404).json({
message: 'Not Found'
})
}
})
.catch(er => {
res.status(500).json({
error: er
});
});
router.get('/:brandSlug', (req, res, next) => {
const slug = req.params.brandSlug;
Brand.findOne({slug: slug})
.select('_id parent')
.exec()
.then(brand => {
if(brand){
Product.find({brand: brand._id})
.select('_id name price productPic brand slug')
.exec()
.then(products => {
res.status(200).json({
message: products
})
})
.catch(error => {
return res.status(404).json({
message: error
})
})
}else{
return res.status(404).json({
message: 'Not Found'
})
}
})
.catch(er => {
res.status(500).json({
error: er
});
});
Category, brand and product schema :
const brandSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true },
slug: { type: String, required: true, unique: true },
const categorySchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true },
slug: { type: String, unique: true },
const productSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true },
slug: { type: String, required: true, unique: true },
price: { type: Number, required: true },
oldPrice: { type: Number, default: 0 },
stock: { type: Number, required: true },
description: { type: String },
productPic: [
{
img: String
}
],
keyword: {type: String},
category: { type: mongoose.Schema.Types.ObjectId, ref: 'Category', required: true },
brand: { type: mongoose.Schema.Types.ObjectId, ref: 'Brand', required: true }
You don't need to do two DB calls to get that required data, Instead you can join those two collections & get required data in one DB call ( Try to read about MongoDB's native $lookup or Mongoose's .populate() - which is a kind of wrapper to $lookup ).
But for now you can replace this :
Product.find({brand: brand._id})
with :
Product.find({brand: mongoose.Types.ObjectId(brand._id)})
Actual issue is brand._id is a string in code (In general when you read docs of brand collection in MongoDB & then log/print it or even use it in code You can see ObjectId()'s are converted to string's as ObjectId() is from BSON & not supported by JSON). So you need to convert input (brand._id) from string to ObjectId() before firing a query to product collection as brand field in product collection is of type ObjectId() !!
Note : Do not forget to import mongoose in this file otherwise it would fail that given point.

How to save document based on user id using mongoose?

I am trying to save template based on user id , How can i make sure when template save it save with user id _id ? i added reference to the templateSchema for User.
user.model.js
var UserSchema = new mongoose.Schema({
_id: { type: String, required: true, index: {unique: true}},
firstName: String,
lastName: String,
type: String,
groups:[{type: String, ref: 'Group', required: false}]
},
{
toObject: {
virtuals: true
},
toJSON: {
virtuals: true
}
});
export default mongoose.model('User', UserSchema);
template.model.js
var User = require('../user/user.model.js');
var TemplateSchema = new mongoose.Schema({
_id: { type: String, required: true},
name: String,
id: String,
appliesTo: [],
properties: [],
createdBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User'}
});
export default mongoose.model('Templates', TemplateSchema);
template.controller.js
var eTemplate = require('./template.model');
export function create(req, res) {
console.log(req.body);
eTemplate.createAsync(req.body)
.then(responseWithResult(res, 201))
.catch(handleError(res));
}
Mongoose has two built-in functions that are called before (pre) and after (post) you save a document. My advice is to make use of them. Here is an example of my code in which I search for an sequence number before saving the user document. You can do the same: When you save the template, make a request for the user id to the database (Or vice-versa). You can even save one, get the id and save the other.
Bellow follows my code for the sequence and the user.
var UserSchema = new Schema({
username: { type: String, required: true, unique: true },
id: { type: String },
...
});
UserSchema.pre('save', function(next) {
let doc = this;
let id = 'userSeq'
Sequence.findByIdAndUpdate(id, { $inc : {nextSId : 1} }, function(error,data) {
if(error)
next(error)
doc.id = data.nextSId-1;
next();
})
});
I hope my answer was useful for you. Just a remark, pre and post are not called in the event of updates for the document.

Fetching an array of document objects with different IDs from a document

I am attempting to show only documents from users in which the session user is subscribed to (in mongo using mongoose). The subscribed users are added to a 'following' array inside the user document. The user can only see objects (posts) from that array.
I am using node express. Here is the attempt using the populate method from mongoose.
var user = req.user;
var posts = [];
Post.populate(posts, {path: "post.creator", match: {'creator': user.following}}, function (err, posts) {
if (err) {
return next(err);
}
posts.forEach(function (post) {
posts.push(post);
});
console.log(posts);
return res.render('subscribed', {posts: posts, user: user});
});
I am new to mongoose, and have only been fetching bulk documents with no queries up until now.
The user model is made up as such:
//required stuff and set up
...
//user object
var UserSchema = Schema({
username: {
type: String,
},
posts: [{
type: Schema.Types.ObjectId,
ref: 'Post'
}],
following: [{
type: Schema.Types.ObjectId,
ref: 'User'
}],
followers: [{
type: Schema.Types.ObjectId,
ref: 'User'
}],
)}
//exports etc
...
And the post schema
//required stuff and set up
...
//post object
var PostSchema = Schema({
title: {
type: String,
required: true,
trim: true
},
createdAt: {
type: Date,
default: Date.now
},
creator: {
type: Schema.Types.ObjectId,
ref: 'User'
}
});
//exports etc
...
Any help would be greatly appreciated.

Categories