inserting in mongo using express - mongodb

i am trying to put data in the mongodb using express but it is storing blank always ...also it is not printing any console logs :
the url i am hitting after starting the sever is
http://localhost:3000/posts?title=test&link=http://test.com
and it is showing the below output:
{"__v":0,"_id":"562717b064002b1c2e697b33","comments":[],"upvotes":0}
router.get('/posts', function(req, res, next) {
console.log('reached ere '+req);
var post = new Post(req.body);
post.save(function(err, post){
if(err){ return next(err); }
res.json(post);
});
});
Post Scheme:
var mongoose = require('mongoose');
var PostSchema = new mongoose.Schema({
title: String,
link: String,
upvotes: {type: Number, default: 0},
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }]
});
mongoose.model('Post', PostSchema);

You are calling your API as
http://localhost:3000/posts?title=test&link=http://test.com
which will send title and link to server as query parameters and not body parameters. So your req.body in this case would be an empty object. That is the reason no data in being saved in your posts collection.
You have two options here:
Change your API to save req.query in posts collection which you can do as follows:
Replace
var post = new Post(req.body);
with
var post = new Post(req.query);
Pass link and title as body parameters instead of query parameters.

Related

TypeError: parent.child.push is not a function - issue pushing my object to database

Problem
I'm trying to send data from my client-side form into my database and am running into the error below:
TypeError: artist.fans.push is not a function
The data is an email address that should be saved into my artist model as a subdoc (in an object).
What I've tried
I'm using the syntax from the mongo docs that says parent.children.push() is the proper way to add subdocs to arrays and parent.children.create() to create new subdocuments. Both yield the same error.
Here's my function:
module.exports.addFanEmail = async (req, res) => {
const fan = req.body;
const artist = await Artist.findById(req.params.id);
artist.fans.create(fan);
await artist.save();
res.redirect(`/artists/${artist._id}`);
}
Right now req.body is only the "fan's" email - here's an example of the object's format: { email: 'tom#test.com' }
DB Model
const artistSchema = new Schema({
image: [ImageSchema],
genre: [ String ],
fans: {
email: String,
subscribed: String,
gender: String,
age: Number
},
});
The object is coming through from the client to the function without any problem, I just can't get it to save to the db?

Express.js PUT Request not updating MongoDB

I'm working on a project that is basically a super watered down social media website.
I have a chunk done already, but I'm having some issues creating a put request to my mongodb. Basically, I want to send a put request to update a numeric value to be able to have a like counter on each post.
What I'm trying do here is send a put request with a specific post id. I'm storing the post id in a hidden text box to reference it. This is pug formatted HTML:
input.form-control(type='hidden' value=item.id id='postId' placeholder='' name='postId' required='false')
form(method='PUT' action='/update/{{post._id}}')
button(type='submit') Like
Then in my router.js file I'm basically trying to take in that id and set the likes field in the Post schema to 1 (just for testing).
router.put('/update/:id', function (req, res, next) {
let id = {
_id: ObjectID(req.params.id)
};
Post.update({_id: id}, {$set:{'likes': 1}}, (err, result) => {
if(err) {
throw err;
}
res.send('user updated sucessfully');
});
});
Here is my post schema
var mongoose = require("mongoose");
var PostSchema = new mongoose.Schema({
postText: {
type: String,
unique: false,
required: true,
trim: true
},
usernameText: {
type: String,
unique: false,
required: true,
trim: true
},
likes:{
type: Number,
unique: false,
required: false
}
});
var Post = mongoose.model("Posts", PostSchema);
module.exports = Post;
Any and all help would be highly appreciated, thank you
You can't change the ObjectId. The ObjectId is generated by MongoDB and can't be changed by the user using query functions.
If you want to assign a unique id to each user for example, then create a separate field in your schema.
You cannot change the ID
'PUT' method is not supported directly as far as I know. You need method override

Why this MongooseDB population method doesn't work?

I wanted to create a database for MTG combos, and doing something very simple like this, using Mongoose and MLab: We have two schemas, Combo and Card, and two instances of a Card model associated with an instance of a Combo model. When I try to populate the combos of the cards with the name of such combo, it doesn't work and it still shows the ID instead of the name.
var mongoose = require('mongoose') ;
mongoose.connect('mongodb://wernerbusch:xxxx!h#ds115340.mlab.com:15340/wernercito');
var Schema = mongoose.Schema;
var comboSchema = new Schema({
name : String,
cards : [{type: Schema.Types.ObjectId, ref:'Card'}],
type : ["infinite mana", "infinite damage", "draw library", "lethal damage", "storm", "graveyard"]
});
var cardSchema = new Schema({
name: String,
colour:["U","R","B","W","G","C"],
combos: [{type:Schema.Types.ObjectId, ref: 'Combo'}]
})
var Combo = mongoose.model("Combo",comboSchema);
var Card = mongoose.model("Card",cardSchema);
var PanderBurst = new Combo({
name:"PanderBurst",
type:'lethal damage'
})
PanderBurst.save(function(err){
if (err) console.log( err)
var SaprolingBurst = new Card({
name: "Saproling Burst",
colour:["G", "R"],
combos : PanderBurst._id
})
var Pandemonium = new Card({
name: "Pandemonium",
colour:["R"],
combos: PanderBurst._id
})
SaprolingBurst.save(function(err){
if (err) console.log( err)
});
Pandemonium.save(function(err){
if (err) console.log( err)
})
});
Card.find().populate('combos', 'name').exec(function(err,cards){
if (err) console.log (err);
})
After this code is executed, nothing changes in the cards documents.
Have you tried:
Card.find().populate({path: "comboes", select: "name"})
.exec((err,cards)=>{
if (err) console.log (err);
console.log(cards);
});
Using an object has always worked for me.
Update:
you also have:
comboes: {type:Schema.Types.ObjectId, ref: 'Combo'}
in your schema
and combos in your populate.
Final Update:
Populate is used when you make a query. Populating a schema during create isn't good practice because it causes duplication, so call populate with each query.

populating associations in mongodb

I'm new to mean and mongodb and was trying to figure out how to populate my answers to my questions. I just changed the words in the platform that I'm learning (examples were posts and comments).
Here's the error message I'm getting.
/Users/joerigby/Documents/codingdojo/full mean/blacktest3/node_modules/express/lib/view.js:62
throw new Error('No default engine was specified and no extension was prov
^
Error: No default engine was specified and no extension was provided.
at new View (/Users/joerigby/Documents/codingdojo/full mean/blacktest3/node_modules/express/lib/view.js:62:11)
at EventEmitter.render (/Users/joerigby/Documents/codingdojo/full mean/blacktest3/node_modules/express/lib/application.js:569:12)
at ServerResponse.render (/Users/joerigby/Documents/codingdojo/full mean/blacktest3/node_modules/express/lib/response.js:961:7)
at /Users/joerigby/Documents/codingdojo/full mean/blacktest3/server/controllers/answers_c.js:53:12
at Query.<anonymous> (/Users/joerigby/Documents/codingdojo/full mean/blacktest3/node_modules/mongoose/lib/query.js:2112:28)
at /Users/joerigby/Documents/codingdojo/full mean/blacktest3/node_modules/mongoose/node_modules/kareem/index.js:177:19
at /Users/joerigby/Documents/codingdojo/full mean/blacktest3/node_modules/mongoose/node_modules/kareem/index.js:109:16
at process._tickCallback (node.js:355:11)
24 Aug 16:48:22 - [nodemon] app crashed - waiting for file changes before starting...
Below are my codes..
from answers_controller.js on server side
show: function(req, res){
console.log(req.params.id);
Question.findOne({_id: req.params.id})
.populate('answers')
.exec(function(err, question) {
res.render('question', {question: question});
});
}
}
from answer model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectID = require('mongodb').ObjectID;
var AnswerSchema = new mongoose.Schema({
answer: String,
description: String,
likes: {type: Number, default: 0},
created_at: {type: Date, default: Date.now },
_question: {type: Schema.ObjectId, ref: 'Question'}
});
mongoose.model('Answer', AnswerSchema);
from question model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectID = require('mongodb').ObjectID;
var QuestionSchema = new mongoose.Schema({
title: String,
description: String,
created_at: {type: Date, default: Date.now },
answers: [{type: Schema.Types.ObjectId, ref: 'Answer'}]
});
mongoose.model('Question', QuestionSchema);
Let me know if you need anything else to look at.
Thanks for your time.
The error is not with Mongo or Mongoose. Check the stack trace in your error message. The problem is from res.render. In order to use this method you must either configure express to have a default view engine (ejs, jade, etc.) or provide a file extension after 'question' so that it knows which template file to look for in order to render the HTML.
// in your main server file
// set default view engine
app.set('view engine', 'ejs');
// set view folder (where it looks for the template files
app.set('views', pathToViewFolder);
Now you can create a question.ejs file in the folder at pathToViewFolder.

How to access a preexisting collection with Mongoose?

I have a large collection of 300 question objects in a database test. I can interact with this collection easily through MongoDB's interactive shell; however, when I try to get the collection through Mongoose in an express.js application I get an empty array.
My question is, how can I access this already existing dataset instead of recreating it in express? Here's some code:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/test');
mongoose.model('question', new Schema({ url: String, text: String, id: Number }));
var questions = mongoose.model('question');
questions.find({}, function(err, data) { console.log(err, data, data.length); });
This outputs:
null [] 0
Mongoose added the ability to specify the collection name under the schema, or as the third argument when declaring the model. Otherwise it will use the pluralized version given by the name you map to the model.
Try something like the following, either schema-mapped:
new Schema({ url: String, text: String, id: Number},
{ collection : 'question' }); // collection name
or model mapped:
mongoose.model('Question',
new Schema({ url: String, text: String, id: Number}),
'question'); // collection name
Here's an abstraction of Will Nathan's answer if anyone just wants an easy copy-paste add-in function:
function find (name, query, cb) {
mongoose.connection.db.collection(name, function (err, collection) {
collection.find(query).toArray(cb);
});
}
simply do find(collection_name, query, callback); to be given the result.
for example, if I have a document { a : 1 } in a collection 'foo' and I want to list its properties, I do this:
find('foo', {a : 1}, function (err, docs) {
console.dir(docs);
});
//output: [ { _id: 4e22118fb83406f66a159da5, a: 1 } ]
You can do something like this, than you you'll access the native mongodb functions inside mongoose:
var mongoose = require("mongoose");
mongoose.connect('mongodb://localhost/local');
var connection = mongoose.connection;
connection.on('error', console.error.bind(console, 'connection error:'));
connection.once('open', function () {
connection.db.collection("YourCollectionName", function(err, collection){
collection.find({}).toArray(function(err, data){
console.log(data); // it will print your collection data
})
});
});
Update 2022
If you get an MongoInvalidArgumentError: The callback form of this helper has been removed. error message, here's the new syntax using async/await:
const mongoose = require("mongoose");
mongoose.connect('mongodb://localhost/productsDB');
const connection = mongoose.connection;
connection.on('error', console.error.bind(console, 'connection error:'));
connection.once('open', async function () {
const collection = connection.db.collection("Products");
collection.find({}).toArray(function(err, data){
console.log(data); // it will print your collection data
});
});
I had the same problem and was able to run a schema-less query using an existing Mongoose connection with the code below. I've added a simple constraint 'a=b' to show where you would add such a constraint:
var action = function (err, collection) {
// Locate all the entries using find
collection.find({'a':'b'}).toArray(function(err, results) {
/* whatever you want to do with the results in node such as the following
res.render('home', {
'title': 'MyTitle',
'data': results
});
*/
});
};
mongoose.connection.db.collection('question', action);
Are you sure you've connected to the db? (I ask because I don't see a port specified)
try:
mongoose.connection.on("open", function(){
console.log("mongodb is connected!!");
});
Also, you can do a "show collections" in mongo shell to see the collections within your db - maybe try adding a record via mongoose and see where it ends up?
From the look of your connection string, you should see the record in the "test" db.
Hope it helps!
Something else that was not obvious, to me at least, was that the when using Mongoose's third parameter to avoid replacing the actual collection with a new one with the same name, the new Schema(...) is actually only a placeholder, and doesn't interfere with the exisitng schema so
var User = mongoose.model('User', new Schema({ url: String, text: String, id: Number}, { collection : 'users' })); // collection name;
User.find({}, function(err, data) { console.log(err, data, data.length);});
works fine and returns all fields - even if the actual (remote) Schema contains none of these fields. Mongoose will still want it as new Schema(...), and a variable almost certainly won't hack it.
Go to MongoDB website, Login > Connect > Connect Application > Copy > Paste in 'database_url' > Collections > Copy/Paste in 'collection' .
var mongoose = require("mongoose");
mongoose.connect(' database_url ');
var conn = mongoose.connection;
conn.on('error', console.error.bind(console, 'connection error:'));
conn.once('open', function () {
conn.db.collection(" collection ", function(err, collection){
collection.find({}).toArray(function(err, data){
console.log(data); // data printed in console
})
});
});
I tried all the answers but nothing worked out, finally got the answer hoe to do it.
var mongoose = require('mongoose');
mongoose.connect('mongodb://0.0.0.0:27017/local');
// let model = require('./test1');
setTimeout(async () => {
let coll = mongoose.connection.db.collection(<Your collection name in plural form>);
// let data = await coll.find({}, {limit:2}).toArray();
// let data = await coll.find({name:"Vishal"}, {limit:2}).toArray();
// let data = await coll.find({name:"Vishal"}, {projection:{player:1, _id:0}}).toArray();
let data = await coll.find({}, {limit:3, sort:{name:-1}}).toArray();
console.log(data);
}, 2000);
I have also mentioned some of the criteria to filter out. Delete and update can also be done by this.
Thanks.
Make sure you're connecting to the right database as well as the right collection within the database.
You can include the name of the database in the connection string.
notice databasename in the following connection string:
var mongoose = require('mongoose');
const connectionString = 'mongodb+srv://username:password#hosturl.net/databasename';
mongoose.connect(connectionString);