I have created nodejs(expressjs) application with mongodb on Openshift.
and I have pushed my database (mehendiDB) on the mongodb server which I can see on the server by using rockmongo cartridge as follows
admin(2)
api(3)
local(1)
mehendiDB(5)
Comments(10)
Likes(10)
Posts(8)
Users(9)
system.indexes(4)
Though I can see the data uploaded onto server but when I retrive it with the following code from my users.js I do not get anything but an empty array. Code I ave written in users.js is as follows
var express = require('express');
var router = express.Router();
var mongodb = require('mongodb');
router.dbServer = new mongodb.Server(process.env.OPENSHIFT_MONGODB_DB_HOST,parseInt(process.env.OPENSHIFT_MONGODB_DB_PORT));
router.db = new mongodb.Db(process.env.OPENSHIFT_APP_NAME, router.dbServer, {auto_reconnect: true});
router.dbUser = process.env.OPENSHIFT_MONGODB_DB_USERNAME;
router.dbPass = process.env.OPENSHIFT_MONGODB_DB_PASSWORD;
router.db.open(function(err, db){
if(err){ throw err };
router.db.authenticate(router.dbUser, router.dbPass, {authdb: "admin"}, function(err, res){
if(err){ throw err };
});
});
router.get('/', function (req, res){
router.db.collection('Users').find().toArray(function(err, names) {
console.log("Printing output : " + names);
res.header("Content-Type:","application/json");
res.end(JSON.stringify(names));
});
});
module.exports = router;
PS : I am not getting any errors in the log console(nodejs.log) when I checked it. and showing 'Printing output'
Thanks in advance.
Have you verified that the database name that you uploaded your data to is the same as the process.env.OPENSHIFT_APP_NAME that you are using within your application?
Related
edit: added image of collection
edit2: after a few debugging, i tried to save a document and run the find() query, and it worked (i found the test document i saved). i think the problem now is somewhere in the connection to the db. i may be connecting to somewhere else
edit3 changed title because it doesnt seem to point to the actual problem.
after a few debugging, i found out that mongoose is querying to somewhere else aside from the database i specified in uri. when i tried to save a test document, it was saved successfully and i was able to get it back using find(). However when i used find(), it only returned the previously saved test document. So now im wondering where are these documents saved?
to add more details, here are some of the codes ive written:
apiServerRoutes.js
'use strict';
module.exports = function(app) {
var apiServer = require('../controllers/apiServerControllers');
app.route('/items')
.get(apiServer.get_all_item);
app.route('/items/:itemId')
.get(apiServer.get_item);
};
apiServerControllers.js
'use strict';
var mongoose = require('mongoose');
var Item = mongoose.model('item_m');
exports.get_all_item = function(req, res) {
console.log("get_all_item() is called");
Item.find({}, function(err, item) {
if (err)
res.send(err);
res.json(item);
});
};
exports.get_item = function(req, res) {
console.log("get_item() is called");
Item.findOne({item_typeId: req.params.typeId}, '',function(err, item) {
if (err)
res.send(err);
res.json(item);
});
};
ItemSchema.js
'use strict';
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ItemSchema = mongoose.Schema({
item_name: String,
item_desc: String,
item_type: String,
});
var Item = mongoose.model('item_m', ItemSchema, 'item_m');
module.exports = Item;
server.js
var express = require('express'),
app = express(),
port = process.env.PORT || 3000,
mongoose = require('mongoose'),
Item = require('./api/models/ItemSchema'),
bodyParser = require('body-parser');
mongoose.Promise = global.Promise;
mongoose.set('debug', true);
mongoose.connect('mongodb+srv://[[user]]:[[pass]]#market-test-app-1dza9.mongodb.net/test?retryWrites=true&w=majority', {
useNewUrlParser: true, useUnifiedTopology: true});
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
console.log("Connection Successful!");
});
var routes = require('./api/routes/apiServerRoutes');
routes(app);
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.listen(port);
console.log('RESTful API server started on: ' + port);
end of edit3
the stuff below this are from the original question i had before i did some digging and debugging
So I have this controller function which uses a simple find query with no projection parameters
exports.get_all_item = function(req, res) {
Item.find({}, function(err, item) {
if (err)
res.send(err);
res.json(item);
});
};
Everytime I run my request in postman, I get an empty result. When I turned debug mode on in express, I saw this query sent by mongoose
Mongoose: item_m.find({}, { projection: {} })
When I try to run this query in mongodb, i get this error
"message" : ">1 field in obj: {}",
If I do add a parameter for projection eg. item_name, mongoose sends this:
Mongoose: item_m.find({}, { projection: { item_name: 1 } })
and when run that query in mongodb, i get this error
"message" : "Unsupported projection option: projection: { item_name: 1.0 }",
But when I change the query to
db.item_m.find({}, { item_name: 1 } )
It works fine, returning the results that Im expecting.
Im still new to both express, node.js, and mongodb. Is this some version problem between mongodb and mongoose?
Im using 4.0.13 for mongodb and 5.8.3 for mongoose but from what I researched, this should be fine. What other stuff am I missing here? Or what ever stuff should I check into that I may have missed?
Thanks in advance.
I use fetch all query using this method. I have tweaked it for your need.
exports.get_all_item = (req, res, next) => {
Item.find()
.select("item_name")
.exec()
.then(items => {
if (items.length > 0) {
res.status(200).json(items);
} else {
res.status(204).json({
message: "No items available"
});
}
})
.catch(error => {
next(error);
});
};
Hope it helps :)
When I checked back in my DB using mongodb atlas, I found that there were two existing databases: master (where I keep my data) and test (im not sure how this was created, but it existed). The entire time mongoose was accessing test and not master. I changed the 'test' in my URI to 'master' and it worked fine.
So I guess the lesson here is to double check the URI; and when debugging, try saving a sample data and find where that data is saved.
I'm a total beginner at this and am using a tutorial to learn the basics of the MEAN stack. I am trying to return the documnents in my database to a web page but am instead receiving an empty array.
I have created a cluster on Mongodb Atlas called mytasklist. Inside here I created a database called mytasklistdb. Inside this I have a table (object) called mytasklistdb.mytasklisttutorial. My understanding of this is limited and so maybe I'm making a huge error somewhere here. I have experience of SQL but not Mongo and so the whole 'clusters' and 'collections' thing is new to me.
Anyway my code is as follows. I took the string for the database connection from the Mongo connection tab.
var express = require('express');
var router = express.Router();
var mongojs = require('mongojs');
var db = mongojs('mongodb+srv://myusername:mypassword#mytasklist-qx0ka.mongodb.net/test?retryWrites=true&w=majority', ['mytasklisttutorial']);
router.get('/tasks', function(req, res, next){
db.mytasklistdb.find(function(err, tasks){
if(err){
res.send(err);
}
res.json(tasks);
});
});
module.exports = router;
My database objects look like this:
_id:5db5f1f31c9d440000c3e7fe
title:"Walk the dog" - this is a string
isDone:false - this is boolean
I'm just getting an empty array but in the tutorial the guy is getting these 'documents'. What am I doing wrong?
EDIT: I realised that the 'tasks' part of the tutorial example was relating to a database called 'tasks'. Mine is called 'mytasklistdb'. I therefore changed this. I also added a parameter with the name of my collection to the line passed in to mongojs.
I have changed my code above to reflect this
The solution was to replace 'task' and 'test' with the name of my db. As follows:
var express = require('express');
var router = express.Router();
var mongojs = require('mongojs');
var db = mongojs('mongodb+srv://James:Noentry1#mytasklist-qx0ka.mongodb.net/mytasklistdb?retryWrites=true&w=majority', ['mytasklisttutorial']);
router.get('/tasks', function(req, res, next){
db.mytasklisttutorial.find(function(err, tasks){
if(err){
res.send(err);
}
res.json(tasks);
});
});
module.exports = router;
My guess is that you are not passing your query, just the callback in the find() method, probably you need to do something like this:
db.tasks.find({},function(err, tasks){
if(err){
res.send(err);
}
res.json(tasks);
});
Why does res.json respond with an empty array?
I want to get all data from collection distributor ,so for that I have
created model file and then assigned it to on variable Distributordata
Server file : app.js
var express=require('express');
var app=express();
var bodyParser=require('body-parser');
var mongoose=require('mongoose');
var Distributordata=require('./distributor.model');
var db='mongodb://localhost/Distributordata';
mongoose.connect(db);
var port=8080;
app.get('/',function(req,res){
res.send("happy to be here");
});
app.get('/distributor',function(req,res){
// res.send("hi from distributors")
console.log("getting all distributors");
Distributordata.find(function(err,distributordata){
if(err){
res.send("error has occured");
}
else{
console.log(distributordata);
res.send(distributordata);
}
});
});
app.listen(port,function(){
console.log('app listening on port'+port);
});
Model file : distributor.model.js
var mongoose=require('mongoose');
var Schema = mongoose.Schema;
var DistributorSchema=new Schema({
dname:String,
daddress: String
});
module.exports=mongoose.model('Distributordata',DistributorSchema);
output
on cmd:
app listening on port8080
getting all distributors
[ ]
So far I've understood your problem is you are creating your collection in mongodb by yourself as the collection name distributor. And also as you are not sending any post request so your code will not create any collection automatically in the main database.
But, by default mongoose always creates a collection name by pluralizing the name of the model, in your case this collection name would be distributordatas. But when, you are trying to get the data from your database, it's getting the collection name as distributor for this reason it becomes unable to make a connection. But you can keep this using force naming convention for collection as like you want.
In your distributor.model.js file change this line of code to this one:
module.exports = mongoose.model('Distributordata', DistributorSchema, 'distributor');
Hopefully, it'll solve your problem. For more reference check this out https://mongoosejs.com/docs/guide.html#collection
I am trying to insert a sub document into all existing documents in a collection in db,in nodejs using express framework.Following is the code snippet:
updatedoc: function(update,options,cb)
{
return this.update({},update,options).exec(cb);
}
where parameters update and options are as follows :
const update = { $push: { "defaultads": content }};
const options = { multi: true};
It seems to run and gives the following output on the console :
{ n: 1, nmodified: 1, ok: 1 }
but no push takes place at all ,in any of the documents of the database.
I have checked :
1) whether i am pushing in the right db.
2) whether correct values are being passed
However I am not able to find where I am going wrong.
I am new to nodejs and would really appreciate guidance in solving this problem.
Thanks in advance.
I am giving a simple code with full fledged requirement of yours. First create a config.js using this file you will be connected to mongodb.Here is the code
module.exports = {
'secretKey': '12345-67890-09876-54321',
'mongoUrl' : 'mongodb://localhost:27017/product'
}
Next create a models folder . Keep this schema in this models folder . I named it as product.js. Here is the code
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var imageSchema = new Schema({
imagepath:{
type:String
}
});
var nameSchema = new mongoose.Schema({
productName:{type: String},
productPrice:{type: Number},
imagePaths:[imageSchema]
});
module.exports = mongoose.model("product", nameSchema);
Next create a routes folder and keep this routes code in this folder I named it as route.js. Here is the code
var express = require('express');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var Product = require('../models/product');
var app = express();
var Router = express.Router();
Router.use(bodyParser.json());
Router.get('/product',function(req,res){
Product.find({}, function (err, product) {
if (err) throw err;
res.json(product);
});
})
Router.post('/productData',function(req, res, next){
Product.create(req.body, function (err, product) {
if (err) throw err;
console.log('Product Data created!');
var id = product._id;
res.writeHead(200, {
'Content-Type': 'text/plain'
});
res.end('Added the product data with id: ' + id);
});
})
Router.post('/subdocument',function (req, res, next) {
Product.find({},function (err, result) {
if (err) throw err;
for(var i=0;i<result.length;i++){
result[i].imagePaths.push(req.body);
result[i].save(function (err, ans) {
if (err) throw err;
console.log('SubDocument created!');
});
}
res.send("Successfully added");
});
})
module.exports = Router;
Next server code I named it as app.js. Here is the code
var express = require('express');
var bodyParser = require('body-parser');
var Product = require('./models/product');
var mongoose = require('mongoose');
var config = require('./config');
mongoose.connect(config.mongoUrl);
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function () {
console.log("Connected correctly to server");
});
var app = express();
var route=require('./routes/route');
app.use('/route',route);
app.listen(3000,function(){
console.log("Server listening on 3000");
});
Run the server as node app.js.
API's
Use GET method http://localhost:3000/route/product .This is for getting all the product information.
Use POST method http://localhost:3000/route/productData .This for creating document. Post data in json format through request body like
{
"productName" : "sweets",
"productPrice" : "33"
}
You will see the response like this.
First post some documents i.e., post 2 or 3 documents and then you can see the documents with get API as I mentioned above. Then you will see all the documents contains empty sub document. You will see the response like this
And now add the sub document to all using the below api.
Use POST method http://localhost:3000/route/subdocument . Using this you can add a sub document to all the documents like this you need to add sub document
{
"imagepath" : "desktop"
}
You can see the response like this
After this again when you run the get API you can see all the sub documents are added to all documents.
Hope this helps.
I tried searching on the web and found no obvious code samples of how reuse the mongodb.connection object. This is what I have currently and would anyone please verify if this is okay.
var app = express();
var mongodb = require('mongodb').MongoClient, format = require('util').format;
var db = null;
app.get('/api/v1/put/:var1/:var2', function(req, res){
collection = db.collection('collection');
/** .. logic ... **/
});
mongodb.connect('mongodb://127.0.0.1:27017/mydb', function(err, mdb){
db = mdb;
app.listen(8000);
});
Your approach will have problem that once application runs it will register express route. If there is idling connections to your web server, then they will be processed ASAP, that will lead to db is undefined.
In order to prevent this, I would recommend to register express routing only after database is connected.
As well you can cache collections instead of getting them on each request.
this is just to refactor my question's code to reflect Maksims' suggestion
var app = express();
var mongodb = require('mongodb').MongoClient, format = require('util').format;
mongodb.connect('mongodb://127.0.0.1:27017/mydb', function(err, db){
collection = db.collection('collection');
app.get('/api/v1/put/:var1/:var2', function(req, res){
/** .. logic ... **/
});
app.listen(8000);
});