I'm getting started with the MEAN STACK, so I took their project (about posting articles), and I'm trying to costomize it in order to get the list of all flows that i can filter with angularjs and also findOne by id.
I followed the same thing that they did for articles to create JS files related to flows (flow is my object). So I have a collection named flows that I imported to the same db used by the MEAN STACK (db == mean-dev) and I tryed this code in:
// myApp/serves/models/flow.js
'use strict';
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
// Flow Schema
var FlowSchema = new Schema({
_id: {
type: Number,
default: ''
},
name: {
type: String,
default: '',
trim: true
},
Clients: {
type: Array,
default: '',
trim: true
},
DP Prot: {
type: String,
default: ''
}
/* And 15 others attributes...*/
});
/** Statics */
FlowSchema.statics.load = function(id, cb) {
this.findOne({
_id: id
}).exec(cb);
};
// Define the collection
mongoose.model('Flow', FlowSchema);
And the controllers code:
// servers/controllers/flows.js
'use strict';
/**
* Module dependencies.
*/
var mongoose = require('mongoose'),
Flow = mongoose.model('Flow'),
_ = require('lodash');
/**
* Find flow by id
*/
exports.flow = function(req, res, next, id) {
Flow.load(id, function(err, flow) {
if (err) return next(err);
if (!flow) return next(new Error('Failed to load flow ' + id));
req.flow = flow;
next();
});
};
/**
* New code count Flows
*/
exports.compte = function(req, res) {
var c;
flow.count({}, function(err, count) {
if (err) return next(err);
c = count;
res.jsonp (count);
});
};
/**
* Show Flow
*/
exports.show = function(req, res) {
res.jsonp(req.flow);
};
/**
* List of Flows
*/
exports.all = function(req, res) {
Flow.find().sort('-name').populate('name', 'application').exec(function(err, flows) {
if (err) {
res.render('error', {
status: 500
});
} else {
res.jsonp(flows);
}
});
};
I added also routes... But it doesn't work, do you think that I made some mistakes? thank you in advance for your help
The documentation shows you how: http://mongoosejs.com/docs/guide.html#collection
You can explicitly choose a collection when creating the Schema:
// Flow Schema
var FlowSchema = new Schema({
/* attributes...*/
}, {
collection: 'my-collection'
});
Or you can set it on the created schema later:
// Flow Schema
var FlowSchema = new Schema({
/* attributes...*/
});
FlowSchema.set('collection', 'my-collection');
This was added in Mongoose 3.4 I believe, so check the verison of Mongoose you are using.
See this post for your query on enforcing a collection name:
Mongoose -- Force collection name
var mySchema = new Schema({
foo: bar
}, { collection: qux });
where qux is your collection, assuming you connected to the correct db in your mongo-connect.
Related
I'm new to keystone js. Right now I'm making a web app that has user dashboard. I'm trying to use the method of updateItem upon a user item, which already been indexed / searched / queried in the first parameter of the function.
// KEYSTONE METHOD
User.updateItem({_id: req.params.id}, req.body, {
fields: 'user',
flashErrors: true,
logErrors: true},
function(err) {
if (err) {
console.log("An error happened!");
console.log(err);
} else {
return res.redirect('/dashboard/' + req.params.id);
}
next();
});
Error popped up in console, shows:
{
error: 'invalid configuration',
detail: 'Invalid path specified in fields to update [user] for list User'
}
It seems that it doesn't found the user model. I wanted to console.log if the system found the user model through callbacks params, but this method doesn't have one.
As I said, I'm really new in keystonejs and I'm not even close to understanding it fully of how things really work here.
But, I feel like it's really close to work...
** CODE REF : Dashboard views **
var keystone = require('keystone');
var user = keystone.list("User");
var User = keystone.List("User");
exports = module.exports = function (req, res) {
var view = new keystone.View(req, res);
var locals = res.locals;
// Init locals
locals.currentUser = req.body || {};
view.query('currentUser', user.model.findById(req.params.id));
view.on('post', { action: 'user.update' }, function(next) {
// KEYSTONE METHOD
User.updateItem({_id: req.params.id}, req.body, {
fields: 'user',
flashErrors: true,
logErrors: true},
function(err) {
if (err) {
console.log("An error happened!");
console.log(err);
} else {
return res.redirect('/dashboard/' + req.params.id);
}
next();
});
});
// Render the view
view.render('../dashboard/dashboard-main');
};
** CODE REF : Jade code **
form(method="post")
input(type='hidden', name='action', value='user.update')
.row.mb-4
.col-md-4
label First Name
input.form-control(type="text" name="first" value=currentUser.name.first)
.col-md-4
label Last Name
input.form-control(type="text" name="last" value=currentUser.name.last)
.row.mb-10
.col-md-12
button.btn.btn-primary(type="submit")
i.fa.fa-fw.fa-lg.fa-check-circle
| Save
Here's the User model:
var keystone = require('keystone');
var Types = keystone.Field.Types;
/**
* User Model
* ==========
*/
var User = new keystone.List('User');
User.add({
name: { type: Types.Name, required: true, index: true },
email: { type: Types.Email, initial: true, required: true, unique: true, index: true },
password: { type: Types.Password, initial: true, required: true },
}, 'Permissions', {
isAdmin: { type: Boolean, label: 'Can access Keystone', index: true },
});
// Provide access to Keystone
User.schema.virtual('canAccessKeystone').get(function () {
return this.isAdmin;
});
/**
* Relationships
*/
User.relationship({ ref: 'Post', path: 'posts', refPath: 'author' });
/**
* Registration
*/
User.defaultColumns = 'name, email, isAdmin';
User.register();
Note: I've used yeoman generator for this app, and just added new route file, and jade view file for the user dashboard.
var User = keystone.List("User");
is invalid in your view / route.js. You only use the capitalized .List when you are creating a new List in your model, as it is a class initiation, like you have in your model.
Therefore the correct context for your dashboard view is likely to be:
var keystone = require('keystone');
var user = keystone.list("User");
/* var User = keystone.List("User"); */
exports = module.exports = function (req, res) {
var view = new keystone.View(req, res);
var locals = res.locals;
// Init locals
locals.currentUser = req.body || {};
view.query('currentUser', user.model.findById(req.params.id));
view.on('post', { action: 'user.update' }, function(next) {
// KEYSTONE
/* User.updateItem({_id: req.params.id}, req.body, { */
user.updateItem({_id: req.params.id}, req.body, {
fields: 'user',
flashErrors: true,
logErrors: true},
function(err) {
if (err) {
console.log("An error happened!");
console.log(err);
} else {
return res.redirect('/dashboard/' + req.params.id);
}
next();
});
});
// Render the view
view.render('../dashboard/dashboard-main');
I am using Mongoose/MongoDB and I am trying to associate many comments to one article. My app begins by scraping from a website and then the user has the option to save each article that was scraped into the MongoDB. When the user chooses to save one article, I save it into database. So when a user clicks on one of their saved articles, they can comment on them. Each article has its own comment section I need to retrieve the correct comments.
//My post comment request in JS file
function postComment(){
var articleComment = {
comment: $('#comment').val().trim()
}
$.post('/comments/' + articleID, articleComment).done(function(data){
$('.main-popup').fadeOut();
console.log('DONNE', data);
});
}
//Post route in controller
router.post('/comments/:id', function(req, res){
var newComment = new Comment(req.body);
newComment.save(function(err, doc){
if(err){
console.log(err);
}else{
Comment.findOneAndUpdate({ "_id": doc._id }, { "article": req.params.id }).exec(function(err, doc){
if(err){
console.log(err);
res.send(err);
}else{
res.send(doc);
}
});
}
});
});
//Get request to get correct comments when clicked on specific article
function showCommentBox(){
$('.comments').empty();
$('#comment').val("");
articleID = $(this).attr('data-article-id');
$.get('/comments/' + articleID, function(data){
if(data.article){ //This is undefined*********************
for(var x = 0; x < data.comment.length; x++){
$('.comments').append("<div><h2>" + data.comment[x].comment + "</h2><span><button>×</button></span></div>");
}
}
$('.main-popup').fadeIn();
});
}
//Get route in controller
router.get('/comments/:id', function(req, res){
Comment.findOne({ "article": req.params.id }).populate("article").exec(function(err, doc){
if(err){
console.log(err)
}else{
res.json(doc);
}
});
});
//Article Model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ArticleSchema = new Schema({
title: {
type: String
},
link: {
type: String
},
description: {
type: String
},
img: {
type: String
}
});
var Article = mongoose.model("Article", ArticleSchema);
module.exports = Article;
//Comment Model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var CommentSchema = new Schema({
comment: {
type: String
},
article: {
type: Schema.Types.ObjectId,
ref: 'Article'
}
});
var Comment = mongoose.model('Comment', CommentSchema);
module.exports = Comment;
First, you're missing $set when you do .findOneAndUpdate. Also I think you should convert a string to Mongo ObjectId before setting it.
So it might look likt this:
const ObjectId = mongoose.Types.ObjectId;
Comment.findOneAndUpdate({ "_id": doc._id }, {$set: {"article": new ObjectId(req.params.id) }})
Also you don't need to make 2 database calls. You could article id before saving newComment and then simply send it as a response like this:
//Please notice that mongoose.Schema.Types.ObjectId and mongoose.Types.Object are different types.
//You need this one here:
const ObjectId = mongoose.Types.ObjectId;
router.post('/comments/:id', function(req, res){
var newComment = new Comment(req.body);
newComment.article = new ObjectId(req.params.id);
newComment.save(function(err, doc){
if (err) {
console.error(err);
res.send(err);
return;
}
res.send(doc);
});
});
i am trying to get the data from mongodb using express server but all i am getting is empty array => []
However if i run the db.Goserv.find() in console i get the results right please help
here is the server.js file
var Schema = mongoose.Schema;
var schema = new Schema({
type: String,
address: String,
servicecost: String
}, { collection: 'Goserv' });
var Goserv = mongoose.model('Goserv', schema );
module.exports = Goserv ;
app.get('/api/centre', function(req, res) {
Goserv.find(function(err, centre){
if(err){
res.send(err);
} else {
res.json(centre);
console.log(centre);
}
});
});
Try this...
var Schema = mongoose.Schema;
var schema = new Schema({
type: String,
address: String,
servicecost: String
}, { collection: 'Goserv' });
var Goserv = mongoose.model('Goserv', schema );
module.exports = Goserv ;
app.get('/api/centre', function(req, res) {
Goserv.find({},function(err, centre){
if(err){
res.send(err);
} else {
res.json(centre);
console.log(centre);
}
});
});
I have mongoose model file like this
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var testSchema = new Schema({
name: { type: String },
username: { type: String },
provider: { type: String },
accessToken: { type: String },
testId: { type: String }
});
/**Indexing*/
testSchema.index({ testId: 1, accessToken: 1 });
testSchema.statics = {
get: function (id, callback) {
this.findOne({'testId': id}, function(error, items){
callback(error, items);
});
},
create: function (data, callback) {
var test = new this(data);
test.save(callback);
}
};
var test = mongoose.model('test', testSchema);
/** export schema */
module.exports = {
Test: test
};
it is working Good with an express app. But I would like to use this model to view and insert data from command line. So, here is my approch which is not working
var Test = require('./app/model/test').Test;
Test.get({'testId': 1},function(err,res){
if(!err){
console.log(res);
}else{
console.log(err);
}
I see two problems:
you're not calling mongoose.connect() anywhere, so it's not connecting to the database
it looks like you should pass the id as an argument to get(); now you're passing it a query. Try this: Test.get('1', ...)
I want to write a rest api, with which i am able to download some data. All datas were stored in a mongodb. I don't know what to pass to the download method, to make it possible.
Here is my current code:
router.get('/download/:productId/:username/:token', function (req, res) {
var auth = require('../provider/authProvider.js');
var authInst = new auth();
authInst.checkAuth(req.params.username, req.params.token, res, function (err, obj) {
if (obj == true) {
res.status(200);
// here is my problem, what to pass to the download-method
res.download('');
}
});
});
I could not find anything else, than passing paths to the download method.
Does anyone has an idea how to solve my problem?
I assume you know how to set up mongoose environment, putting config, connecting to MongoDB. If not please refer to my answer here.
Now let's say we have a Document in MongoDB as Blog.
So we need to create a model for Blog so that we can do CRUD operations using Mongoose ORM.
you need mongoose module for this to be included in your project.
so run this command from your project root directory, it will automatically download mongoose for you.
npm install mongoose --save
BlogModel.js
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var BlogSchema = new Schema({
"title" : { type: String },
"user_id" : { type: String },
"blog_uri" :{ type: String },
"post_date" : { type : Date, default: Date.now},
"body" : { type: String, default: '' },
"comments" : [
{ 'content' : { type: String },
'user_id' : { type: String },
'comment_date' : { type: Date },
'votes' : [
{
'user_id' : { type: String }
}
]
}
],
"hidden" : {type:Boolean, default: false }
});
mongoose.model('Blog', BlogSchema);
So let's create a separate file called BlogController.js where we will write methods for CRUD.
var mongoose = require('mongoose');
var Blog = mongoose.model('Blog');
var ObjectId = require('mongoose').Types.ObjectId;
exports.create = function(req,res){
var blog = new Blog(req.body);
blog.save(function(err){
if(err)
res.json({message: "Error occured while saving"});
else{
res.redirect('/home');
}
});
};
exports.getAll = function(req,res){
Blog.find(function(err,blogs){
if(err){
res.send(err);
}else{
res.json(blogs);
}
});
};
exports.get = function(req,res){
var id ;
try{
id = new ObjectId(req.params.id);
Blog.findById(id,function(err,blog){
if(err){
res.send(err);
}else{
res.render('blog.ejs', {
blog: blog
});
}
});
}catch(e){
res.send(404);
}
};
exports.update = function(req,res){
var id ;
try{
id = new ObjectId(req.params.blog_id);
Blog.findById(id,function(err,blog){
if(err){
res.send(err);
}
blog.save(function(err){
if(err)
res.send(err);
res.render('blog.ejs', {
message: "Blog Updated successfully"
});
});
});
}catch(e){
res.send(404);
}
};
exports.delete = function(req,res){
var id ;
try{
id = new ObjectId(req.params.blog_id);
Blog.remove({_id:id},function(err,blog){
if(err){
res.send(err);
}
res.render('blog.ejs', {
message: "Blog deleted successfully"
});
});
}catch(e){
res.send(404);
}
};
So this was about CRUD using Mongoose. I usually don't use res.render(..) in my projects because i put Templating logic in front end. I just use res.json(..) and pass the json data to the the frontend. So please go ahead and try. I hope i answered your question. You can refer to
this repo, for better example. Here i got a very clean CRUD implementation.