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)
Related
i am a quite new to mongoose and mongodb and have been trying to connect my user with a bunch of image posts. I read a lot about mongoose populate but i keep on getting empty images [].
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
email: {
type: String,
required: true
},
username: {
type: String,
required: true
},
password: {
type: String,
required: true
},
images: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Image'
}
]
});
module.exports = mongoose.model('User', userSchema);
const mongoose = require('mongoose');
const imageSchema = new mongoose.Schema({
id: mongoose.Schema.Types.ObjectId,
image: {
type: String,
required: true
},
description: {
type: String,
required: true
},
})
module.exports = mongoose.model('Image', imageSchema);
const getOne = async (userId) => {
let lastTenImages = await User.findById(userId).populate('images').lean();
console.log(lastTenImages.images);
// return lastTenImages
}
I also used mongoose.Types.ObjectId instead of Schema but still got the same result- an empty array
In my opinion you should discard the id portion which is not working as the link to the User model. In other words try something like:
const imageSchema = new mongoose.Schema({
image: {
type: String,
required: true
},
description: {
type: String,
required: true
},
})
I think that should populate the right array.
In addition, when you get the value you will be getting an array of objects. So you would need to map over it. lastTenImages.images won't produce anything.
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.
This may seem like a vague question, but I'm going to try to explain the best I can. As a side note, I'm quite new to using mongoose :)
I have a mongoose-schema storing different values for each user, like so...
let userSchema = mongoose.Schema({
user: { type: String, required: true, unique: true },
pass: { type: String, required: true },
files: [{ type: String, required: false }],
});
The "files"-key contains an array of values, lets say for example:
userSchema.files = [value1, value2, value3]
And I want each value to be connected to some kind of ID, so that when I call the specified ID, I get the specified value. Just for demonstrating purposes, it could look something like this:
userSchema.files = [{value:value1, id: id1},
{value:value2, id: id2},
{value:value3, id: id3}]
Then I want to find the specified id, and return it's "value"-key in a request:
router.route("/home/:id")
.get(restrict, function(req, res) {
User.findOne({ user: req.session.Auth.username }, function(error, data) {
data.files.forEach(function(file) {
if (file.id === req.params.id) {
response.render("../home", file.value)
}
}
});
});
How can I do this? Tried pushing an object to files, but that didn't work as expected. Read something about ObjectId, but couldn't quite understand it. Any tips?
I think you simply need to create a separate model for File and connect it to your User model using the 'ref' keyword :
let fileSchema = mongoose.Schema({
_id : Number,
value : String
});
let userSchema = mongoose.Schema({
user: { type: String, required: true, unique: true },
pass: { type: String, required: true },
files: [{ type: Number, ref: 'File' }]
});
let User = mongoose.model('User', userSchema);
let File = mongoose.model('File', fileSchema);
let f1 = new File({ _id: 1, value: 'File 1'});
let f2 = new File({ _id: 2, value: 'File 2'});
let f3 = new File({ _id: 3, value: 'File 3'});
let user1 = new User({user:'chuck', pass:'norris'});
user1.files.push(f1);
user1.files.push(f2);
user1.files.push(f3);
user1.save(function(err){ });
Now to get the data back:
User
.findOne({ user: 'chuck' })
.populate('files') // only works if we pushed refs to children
.exec(function (err, user) {
if (err) return handleError(err);
console.log(user);
//you can now loop through user.files and compare _id
user.files.forEach(function(file) {
if (file._id === req.params.id) {
response.render("../home", file.value)
}
}
});
You can read about mongoose reference population here: http://mongoosejs.com/docs/populate.html
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.
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.