URL Shortener - FInding and reading from the right Mongo collection from mLab via Mongoose

Beginning to hit a wall here.

In line 17 of the code below, I am just trying to find the matching collection. Two lines down from that I am trying to fire off a redirect with the matching url.

I am still just not getting the sequence of commands correct for reading this information from mongo. I get the error “TypeError: Cannot read property ‘find’ of undefined”

(If this was sql I would be writing something like FROM urlcntrctr SELECT “url” WHERE key = “123xyz”)

This is the last piece of the puzzle before I can get this working in Node. What am I doing wrong?

ALSO, how is the redirect triggered correctly?

app.get('/:tag(*)', function(req, res) {
  var targetnumber = req.params.tag; 
  sendforRedirect(targetnumber); 
    closetheconnection()
}) 

function sendforRedirect(target){  
     var mongoose = require('mongoose');
     var target = target;
     var options = { server: { socketOptions: { keepAlive: 300000, connectTimeoutMS: 30000 } }, 
          replset: { socketOptions: { keepAlive: 300000, connectTimeoutMS : 30000 } } };       
     var mongodbUri = 'mongodb://<username>:<password>@ds159988.mlab.com:59988/urlcntrctr';
        mongoose.connect(mongodbUri, options);
       var conn = mongoose.connection;             
        conn.on('error', console.error.bind(console, 'connection error:'));  
        conn.once('open', function() {
          var targetArray = mongodbUri.documents.find({ key: target 
          })
          var curr_url = targetArray[0]["url"];
          redirect(curr_url);
          });
        }); 
}

mongodUri is a string. As a sting it doesn’t have a property document so trying to read document results in an undefined (the string gets wrapped by an object and that object doesn’t have a document property). Hence what happened. Trying to read find of undefined ends in a type error because undefined is not an object and doesn’t have properties.

If you want to use mongoose you need to use schemas. It will take too long to explain properly so I strongly recommend you check this course here: https://www.edx.org/course/introduction-mongodb-using-mean-stack-mongodbx-m101x-0 (I found out about it from P1xt’s post)

Generally, schemas go like this (you’ll also want to setup an environment variables config file with dotenv):

const Schema = mongoose.Schema
mongoose.connect(process.env.MONGODB_URI) // you'll need this for heroku

const MySchema = new Schema({
  _id:  { type: Number, index: true },
  content: String
})

const SchemaName = mongoose.model('SchemaName', MySchema)

SchemaName.findOne({ content: 'myquery' }, function (err, doc) { ... })
1 Like

Thanks, that helped out enormously and at least I got it to stop returning that error.

Would you have any idea why the new code is failing to match a key with a collection in the database that has that key?

var express = require('express')
var app = express()
var path = require('path');
var port = process.env.PORT || 8080;
var crypto = require("crypto");
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
    url : String,  
    key : String   
  });

app.get('/', (req, res, next) => res.sendFile(path.join(__dirname, '/index.html')));

app.set('port', (process.env.PORT || 5000));

app.get('/:tag(*)', function(req, res) {
  var targetnumber = req.params.tag; 
  sendforRedirect(targetnumber); 
}) 

function sendforRedirect(target, res){  
 var mongoose = require('mongoose');
 var target = target;
 var options = { server: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } }, 
      replset: { socketOptions: { keepAlive: 1, connectTimeoutMS : 30000 } } };       
 var mongodbUri = 'mongodb://<username>:<password>@ds159988.mlab.com:59988/urlcntrctr';
    mongoose.connect(mongodbUri, options);
    
   var conn = mongoose.connection;             
    conn.on('error', console.error.bind(console, 'connection error:'));  
    conn.once('open', function() {
      console.log("OK, you are connected for the redirect. ") 
      var mongoose = require('mongoose');
      var Schema = mongoose.Schema;
      const SchemaName = mongoose.model('SchemaName', UserSchema);
      SchemaName.findOne({ key: target }, function (err, doc) {
      if(err){
        console.log(err);
        closetheconnection();
      };
      if(doc){
        res.redirect(doc.original_url);
        closetheconnection();
      } else {
        console.log("Sorry, we don't recognize that url");
        closetheconnection();
      }
     }); 
    }); 
}

Here is what the collection looks like in the db:

{
  "_id": {
      "$oid": "588292e15d0d5904bfb0b5db"
  },
  "key": "ISaHgM",
  "url": "http://www.drudgereport.com/",
  "__v": 0
}

And here is the request:

https://firstappever-olddognewtrix123.c9users.io/ISaHgM

Hmm… it is because my query is returning a null…

It may be different in mongoose but in mongo you have to specify the db in the db.connect function.

var col = db.connect ("collection_name");

@Josh5231 you are right about that.

@olddognewtrix123 in mongoose you don’t necessarily have to point to the collection. That said, if you already have an existing collection that you would want to use then you have to use this:


var urlSchema = new Schema({ url : String, key : String }, 
  {collection: 'urlcntrctr'});

For this to work I think you should also connect to mongodb://:@ds159988.mlab.com:59988/ and skip the urlcntrctr

PS I did manage to make your code work on my 127.0.0.1 with an existing collection. Except for res.redirect and closetheconnection

I would use a console.log to see what the value of “target” is at run time. Make sure it matches what you are intending to query in the DB.

Thanks. I made updates to the code … and am still getting “null” for docs!

Still not getting what I’m getting wrong with the .find function.

Any help anyone can offer will be appreciated. I am all ears.

Here is the collection:

{
"_id": {
"$oid": “588292e15d0d5904bfb0b5db”
},
“key”: “ISaHgM”,
“url”: “http://www.drudgereport.com/”,
"__v": 0
}

Here is the request I am sending to the server:

https://firstappever-olddognewtrix123.c9users.io/ISaHgM

Here is the code:

var express = require('express')
var app = express()
var path = require('path');
var port = process.env.PORT || 8080;
var crypto = require("crypto");
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

app.get('/:tag(*)', function(req, res) {
 var targetnumber = req.params.tag; 
  sendforRedirect(targetnumber); 
}) 

 function sendforRedirect(target, res){  
   var mongoose = require('mongoose');
   var target = target;
 
   var options = { server: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } }, 
      replset: { socketOptions: { keepAlive: 1, connectTimeoutMS : 30000 } } };       
   var mongodbUri = 'mongodb://gigglescaptain:againrides!1@ds159988.mlab.com:59988/urlcntrctr';
     mongoose.connect(mongodbUri, options);
    
    var conn = mongoose.connection;             
     conn.on('error', console.error.bind(console, 'connection error:'));  
      conn.once('open', function() {
       console.log("OK, you are connected for the redirect. ") 
       var mongoose = require('mongoose');
       var Schema = mongoose.Schema;
       var urlSchema = new Schema({ url : String, key : String }, {collection: 'urlcntrctr'});
       //const SchemaName = mongoose.model('SchemaName', UserSchema);
       const SchemaName = mongoose.model('SchemaName', urlSchema);
       SchemaName.findOne({ "key": target }, {url:1, _id:0}, function (err, doc) {
         console.log(target)
         console.log(doc) // doc is returning null!!!!!!
      if(err){
         console.log(err);
         closetheconnection();
       };
       if(doc){
         res.redirect(doc.original_url);
         closetheconnection();
       } else {
         //res.send("Sorry, we don't recognize that url");
         console.log("Sorry, we don't recognize that url");
         closetheconnection();
       }
      }); 
     }); 
 }

Here is the activity on the Node terminal:

olddognewtrix123:~/workspace/urlcntrctr $ node server.js
Node app is running on port 8080
OK, you are connected for the redirect.
ISaHgM
null
Sorry, we don’t recognize that url

Your problem is that you can’t find the collection you are looking for. You are getting null because there is no such document. I think that if you use mongodb://gigglescaptain:againrides!1@ds159988.mlab.com:59988/ instead of mongodb://gigglescaptain:againrides!1@ds159988.mlab.com:59988/urlcntrctr it will work.

Try it with this code:


var express = require('express')
var app = express()
var path = require('path');
var port = process.env.PORT || 8080;
var crypto = require("crypto");
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var urlcntrctr = new Schema(
  { url : String, key : String },
  { collection: 'urlcntrctr' }
);

const SchemaName = mongoose.model('SchemaName', urlcntrctr);

app.get('/:tag(*)', function(req, res) {
  var targetnumber = req.params.tag;
  sendforRedirect(targetnumber, res);
})

app.listen(port, console.log(`listening on port ${port}`));


function sendforRedirect(target, res){
  var options = {
    server: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } },
    replset: { socketOptions: { keepAlive: 1, connectTimeoutMS : 30000 } }
  };
  var mongodbUri = 'mongodb://gigglescaptain:againrides!1@ds159988.mlab.com:59988';
  mongoose.connect(mongodbUri, options);
  var conn = mongoose.connection;
  conn.on('error', console.error.bind(console, 'connection error:'));
  conn.once('open', function() {
    console.log("OK, you are connected for the redirect. ")
    SchemaName.findOne({ key: target }, function (err, doc) {
      if(err){
        console.log(err);
        conn.close();
      };
      if(doc){
        res.send(doc.url);
        conn.close();
      } else {
        console.log("Sorry, we don't recognize that url");
        conn.close();
      }
   });
  });
}


1 Like

That worked! I didn’t even think to look at the connection string, focusing instead on the query syntax further down. It just goes to show that ultimately you can’t do coding alone - so many times it takes a second set of eyes! Thank you again.

Actually, dang, no that didn’t work. I am still getting an authentication error unless I include the db in the connection string.

So I am back to the old problem: my findOne statement simply is not pulling in any data from mLab via mongoose.

The connection connects, it stays open and does not close before the function is completed, but the findOne query returns null.

What am I missing? (problem function, ‘sendforRedirect,’ is at the very bottom)

var express = require('express')
var app = express()
var path = require('path');
var port = process.env.PORT || 8080;
var crypto = require("crypto");
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var UserSchema = new Schema({ // this schema is used for writing to the db
   url : String,  
   key : String   
  });

var urlcntrctr = new Schema( // this schema is used for reading from the db
    {url : String, key: String },
    { collection: 'urlcntrctr'}
    );

const SchemaName  = mongoose.model('SchemaName', urlcntrctr); // for reading from the db

app.get('/', (req, res, next) => res.sendFile(path.join(__dirname, '/index.html')));

app.set('port', (process.env.PORT || 5000));

app.get('/:tag(*)', function(req, res) {
  var targetnumber = req.params.tag; //So, if'https://firstappever-olddognewtrix123.c9users.io/ISaHgM', returns 'ISaHgM'
  sendforRedirect(targetnumber, res); 
}) 

function sendforRedirect(target, res){  
     var options = { server: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } }, 
          replset: { socketOptions: { keepAlive: 1, connectTimeoutMS : 30000 } } };       
    //var mongodbUri = 'mongodb://dbusername:dbuserpassword@ds159988.mlab.com:59988'; //this gives me an authentication error
    var mongodbUri = 'mongodb://dbusername:dbuserpassword@ds159988.mlab.com:59988/urlcntrctr'; //this gets me in but "Sorry, we don't recognize that url"
        mongoose.connect(mongodbUri, options);
        mongoose.Promise = global.Promise;
       var conn = mongoose.connection;             
       conn.on('error', console.error.bind(console, 'connection error:'));  
        conn.once('open', function() {
          console.log("OK, you are connected for the redirect. ") 
         SchemaName.findOne({key:target}, { key: 1, url: 1, _id: 0 }, function (err, doc) {
         if(err){
            console.log(err);
            conn.close();
         };
          if(doc){
            res.send(doc.url);
            conn.close();
          } else {
            res.send("Sorry, we don't recognize that url");
            console.log("What is in 'doc' 2: " + doc)
            conn.close();
          }
         }); 
        }); 
}