I am making an application in express using mongoose. I have a collection called users in which there is a filed called _subscriptions, which is an array of objects and each object contains a field named field which is an ObjectId for the documents of fields (this is another collection in my db).
I want to make such an API which after getting id parameter returns me a user form users collection with field attribute populated instead of its id in value of the field field. For this I am using populate method but it is not working.
This is screenshot showing users collection:
This is screenshot showing fields collection:
This is schema for field (File name Field.js):
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var FieldSchema = new Schema(
{
_id: Schema.Types.ObjectId,
name: String,
price: Number,
_categories: [{
type: Schema.ObjectId,
}],
}
);
module.exports = mongoose.model('Field', FieldSchema);`
This is schema and model for users
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
_id: Schema.Types.ObjectId,
salt: String,
provider: String,
name: String,
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
_subscriptions: [{
field: {
type: mongoose.Schema.ObjectId,
ref: 'Field',
},
status: String,
dateSubscribed: Date,
payments: [{}]
}],
role: String,
});
module.exports = mongoose.model('User', UserSchema);
This is code for user router
var Field = require('../model/Field');
var express = require('express');
var router = express.Router();
var User = require('../model/User');
router.get('/',function(req, res, next) {
User.find({}, function(err, result) {
if (err) {
console.log(err);
res.send('something wrong');
}
res.status(200).send(result);
}).populate( '_subscriptions.field').exec(function (err, story) {
if (err) return handleError(err);
console.log('Here!!!!!');
});
});
router.get('/findById/:id',function(req, res, next) {
var id = req.params.id;
User.findById(id, function(err, doc) {
if (err) {
console.error('error, no entry found');
}
res.status(200).send(doc);
}).populate('field').exec(function (err, story) {
if (err) return handleError(err);
console.log('Here!!!!!');
});
});
router.get('/getSubscriptions/:id',function(req, res, next) {
var id = req.params.id;
User.findById(id, function(err, doc) {
if (err) {
console.error('error, no entry found');
}
var type = typeof(doc);
res.status(200).send(doc);
})
});
module.exports = router;
This is where I have called app.use method:
And this is response I am getting using postman
I am looking forward for someones' assistance in resolving this issue
as i am unable to identify my mistake. Your help in this regard will be highly appreciated.
Thanking in advance
What I have understood is, In the user collection, there is _subscriptions and in _subscriptions, there is field. If this is your schema, then you should pass "_subscriptions.field" as a parameter to the populate function not "field" as you have passed currently.
So, your code for user's sub route, /findById/:id, must be like this:
router.get('/findById/:id',function(req, res, next) {
var id = req.params.id;
User.findById(id, function(err, doc) {
if (err) {
console.error('error, no entry found');
}
res.status(200).send(doc);
}).populate('_subscriptions.field').exec(function (err, story) {
if (err) return handleError(err);
console.log('Here!!!!!');
});
});
Related
Tried to insert auto increment number for serial number in mongodb using mongoose and nodejs but not working.Where i want to update my code to find solution.If anyone knows please help to find solution.
subs.model.js:
const mongoose = require('mongoose');
var subscriberSchema = new mongoose.Schema({
_id: {type: String, required: true},
email: {
type: String
}
}, {
versionKey: false,
collection: 'subscribers'
});
module.exports = mongoose.model('Subscribers', subscriberSchema);
data.controller.js:
module.exports.subscribeMail = (req, res, next) => {
var subscribeModel = mongoose.model("Subscribers");
var subscribemailid = req.query.email;
var subscribe = new subscribeModel({
email: subscribemailid
});
var entitySchema = mongoose.Schema({
testvalue: { type: String }
});
subscribe.save(function(error, docs) {
if (error) { console.log(error); } else {
console.log("subscribe mail id inserted");
console.log(docs)
res.json({ data: docs, success: true });
}
});
entitySchema.pre('save', function(next) {
var doc = this;
subscribe.findByIdAndUpdate({ _id: 'entityId' }, { $inc: { seq: 1 } }, function(error, counter) {
if (error)
return next(error);
doc.testvalue = counter.seq;
next();
});
});
};
If i use above code inserting data into mongodb like below:
_id:5f148f9264c33e389827e1fc
email:"test#gmail.com"
_id:6f148f9264c33e389827e1kc
email:"admin#gmail.com"
But i want to insert like this
_id:5f148f9264c33e389827e1fc
serialnumber:1
email:"test#gmail.com"
_id:6f148f9264c33e389827e1kc
serialnumber:2
email:"admin#gmail.com"
You can use this plugin: https://www.npmjs.com/package/mongoose-auto-increment
First you need to initialize it after creating Mongoose connection:
const connection = mongoose.createConnection("mongodb://localhost/myDatabase");
autoIncrement.initialize(connection);
Than in your subs.model.js file:
const mongoose = require('mongoose');
const autoIncrement = require('mongoose-auto-increment');
var subscriberSchema = new mongoose.Schema({
_id: {type: String, required: true},
email: {
type: String
}
}, {
versionKey: false,
collection: 'subscribers'
});
subscriberSchema.plugin(autoIncrement.plugin, {
model: 'Subscribers',
field: 'serialnumber'
});
module.exports = mongoose.model('Subscribers', subscriberSchema);
I have two schema,
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
// Create the User Schema
const UserSchema = new Schema({
email: {
type: String
},
password: {
type: String
}
});
module.exports = User = mongoose.model("users", UserSchema);
OR
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
// Create the Status Schema
const StatusSchema = new Schema({
admin_id:{
type: Schema.Types.ObjectId,
ref: 'users'
},
text:{
type: String
},
});
module.exports = Status = mongoose.model("Status", StatusSchema, "Status");
then i use the populate in my api route:
router.get(
"/",
passport.authenticate("jwt", {
session: false,
}),
(req, res) => {
try {
Status.find({}).populate('admin_id').exec(err, data=>{
console.log(data); // return a blank array : []
return res.sendStatus(200)
})
}
} catch (error) {
res.sendStatus(500);
}
}
);
When i call this route i got an empty array [] .... Any idea what i do wrong? I should mention that i have inserted records in status collection for both admin_id
Is there any onther way to do this ?
There is a lot of ways to do this.
You sould use this,
Status.find({}).then((doc) => {
if (doc) {
Status.populate(doc, { path: "admin_id", model: "users" }, function (
err,
data
) {
if (err) throw err;
console.log(data); //here is your documents with admin user
});
}
});
When I save a new "experience" document with the model Experience, the experience _id is not saved into the document of the user. So my "experiences" array in the user document remains empty. Why?
const mongoose = require('mongoose');
const ExperienceSchema = mongoose.Schema({
name: String,
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
reviews: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Review' }],
categories: [{ type: String }],
});
module.exports = mongoose.model('Experience', ExperienceSchema);
==============================================
const mongoose = require('mongoose');
const UserSchema = mongoose.Schema({
name: String,
experiences: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Experience' }],
});
module.exports = mongoose.model('User', UserSchema);
=============================================
// Update experience to database
router.post('/:id', (req, res, next) => {
const idexp = req.params.id;
const newExperience = {
name: req.body.name,
user: req.user._id,
};
Experience.findOneAndUpdate({ _id: idexp }, newExperience, (err, result) => {
if (err) {
return res.render(`/${idexp}/edit`, { errors: newExperience.errors });
}
return res.redirect(`/experiences/${idexp}`);
});
});
The experiences is the sub-document of user schema. So, when you save experiences, the user will not be saved. However, when you save user, the experience should be saved.
Refer this subdocs documentation
Here is the solution... I needed to use $push to update the user document with the experience id before rendering the site.
Experience.findOneAndUpdate({ _id: idexp }, newExperience, (err, result) => {
if (err) {
return res.render('experiences/edit', { errors: newExperience.errors });
}
User.findByIdAndUpdate({ _id: req.session.passport.user._id }, { $push: { experiences: idexp } }, (err) => {
if (err) {
next(err);
} else {
return res.redirect(`/experiences/${idexp}`);
}
});
});
In Article model, I want to save a list of categories:
var CategorySchema = new Schema({
name: String,
active: Boolean
});
var ArticleSchema = new Schema({
title: String,
description: String,
categories: [{ type : Schema.Types.ObjectId, ref: 'Category' }]
})
From the endpoint, I want to update article with categories. The update method looks like:
exports.update = function(req, res) {
if(req.body._id) { delete req.body._id; }
Article.findById(req.params.id, function (err, article) {
if (err) { return handleError(res, err); }
if(!article) { return res.send(404); }
var updated = _.merge(article, req.body);
updated.save(function (err, doc) {
console.log(doc);
if (err) { return handleError(res, err); }
return res.json(200, article);
});
});
};
Notice the console.log statement. In request.body, if I'm sending list of category ids, the console prints out an article with categories. However, when I look into the database, the category array is empty. Any pointer to how to solve this?
I'm writing my own API in express to perform mongo update queries and I'm having trouble updating the "name" field specifically.
TagHandles.update(
{"uuid":req.params.id},
// {$set: { name : "piers" } },
{$set: { type : "works" } },
{upsert:true,safe:false},
function(err, data){
if (err){
console.log("ERROR");
console.log(err);
console.log(data);
} else {
console.log("SUCCESS");
console.log(err);
console.log(data);
}
res.send(err || data);
});
The TagHandles is a mongoose model with the following Schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var TagHandle = new Schema({
type: String,
uuid: String,
handle: String
}, {
collection: 'tagHandles'
});
var TagHandles = mongoose.model('tagHandles', TagHandle);
Apparently mongoose prevents you from updating any fields not listed as part of the schema. So to correct, I added the line:
name: String
to the mongoose schema.