Mongo Mongoose Simple Tutorial Quick Start Code Example

How's that for a search engine friendly title? It's a combination of the things I tried as I started my experience with Mongo/mongoose that did not give me what I wanted. What I did get were all sorts of useful explanations and advice. What I did not get is a simple bit of working code to satisfy my Hello World needs.

The code below includes the lesson, 'use createConnection(), not connect()'. The former allows you to access the database from separate model classes without having to pass a connection object around. In the depths of the mongoose forums, the fancy guys admit that they prefer createConnection() so it's ok.

It also has my curried default test callback. I had a problem when I tested the example that required it so I left it in so you can solve whatever screws it up for you more easily.

I had two problems you might want to know about:

You will notice that the boilerplate has a peculiar model name (userTqTest). I built this example inside my real, working project. It turns out that Mongo does not forget old model definition stuff. I haven't quite worked out the details but the bottom line is that when I declared this model as User and saved, I got errors based on the validation in my previous, real model. That is, the mongoose model does not supersede the one inside Mongo itself. I got over it by, first, dropping the collection. Then, since I don't want you to have to drop your User collection, I changed it to a name that is very unlikely to collide with you database.

Second is one that you probably will notice instantly but, because I was focused so much on showing the simple syntax, I didn't think about right away is that these calls to save, get and delete are asynchronous. They are triggered in the right order but they are happening in whatever order Mongo takes care of it.

I didn't want to complicate the example with async or some other method to sequence the calls, so I didn't. This code definitely works if you run the three functions one at a time but give unpredictable results otherwise. My problem was that the delete fired before the save was complete leaving the record to give me a duplicate key error on the second pass.

Enjoy.

========================================

        var mongoConnection = mongoose.createConnection("mongodb://localhost:27017/test");
        mongoConnection.on('error', function(err) {
            throw ("user code says, mongoose failed")
        });

        var userSchema = new Schema({
            userName: {
                type: String,
                unique: true
            } /*obviously you'd have more properties*/
        });

        var userAccessor = mongoConnection.model('UserTqTest', userSchema);

        var saveUser = function(user, callback) {
            /*you'd probably do some validation even though the mongoose will also validate
            you'd also wrap stuff in try/catch but that's not the point of this example.*/

            var newUser = new userAccessor(user);
            newUser.save(callback('saveUser' + '/' + user.userName));
        }

        var getUser = function(user, callback) {
            var query = userAccessor.findOne(user);
            query.exec(callback('getUser'));

        }

        var deleteUser = function(user, callback) {
            userAccessor.remove(user, callback('deleteUser'));
        }

        var callback = function(callingName) {
            return function(err, result) {
                console.log(callingName + '============');
                console.dir(err);
                console.dir(result);
                console.log('=====');
            }
        }

        saveUser({
            userName: 'tqwhite'
        }, callback);


        getUser({
            userName: 'tqwhite'
        }, callback);


        deleteUser({
            userName: 'tqwhite'
        }, callback);




   


Running Multiple Versions of NodeJS on One Server

In the modern age, node installation is handled by the 'n', eg,

sudo n stable #the current stable version

or,

sudo n 0.10.40 # to install v0.10.40

Once you have installed a version, it never goes away. You can switch back and forth between versions instantly. That means that you can easily alternate between two (or more) versions if you want.

But, you might (as I did) have an app that must run on an old version but you otherwise want to use a modern version. That is, you want two different versions active at once.

This can be done by referring to the node binary with a fully qualified path. (Remember, when you type "node", your shell is simply giving you /usr/local/bin/node.)

The program 'n' allows you to find the path to the binary (assuming that you have previously installed it), ie,

n bin 0.10.40

->/usr/local/n/versions/node/0.10.40/bin/node

You can then type

/usr/local/n/versions/node/0.10.40/bin/node SOME_OLD_APP.js

into your shell or put it into your initialization script or whatever.

I create separate users for each of the apps I have running on my server. There is only one that requires the old version of node. I want to use the latest stable version for everything else so, I have done "n stable". For the user account where I run the old app, I change my .bash_alias file to include...

alias node="/usr/local/n/versions/node/0.10.40/bin/node"

Then I can type

node SOME_OLD_APP.js

and get good results, or,

node --version

->v0.10.40

But when I log in as the user for a different app, I get the latest stable version.

Obviously, you can do this for as many node versions as you want but, if you need a lot, you might want to think about why (for me, it is Meteor, which only runs on old node).


UPDATE:

I have had occasion since I wrote this to install a new server. I was reminded that the utility 'n' does not come automatically with a NodeJS install. After you install NodeJS (which also installs npm), type

sudo npm install n -g

and the you can verify it by typing

n --help

and you will get all kinds of good info.

Color and Other Format for Fargo.io

Dave Winer is the guru of outlining. He is the person who moved outlines from English class onto the computer in the eighties. He's done a lot of other things, too. But, his development tool Frontier was a game changer for me. I eventually had to leave it behind because my brain needs color. I need code coloring when I'm programming and I need color cues to work productively with an outliner (everything else, too; my emails alway have colored sections).

His newest outline, Fargo, is very cool (at http://fargo.io). It runs in a web browser and saves your files into your Dropbox. Awesome. Unfortunately, it's also black and white and serif type face. I don't like that and, honestly, I have a hard time working with black type if there is very much of it. I tried it out. Liked it. I continued to use Omni Outliner. (If I could get Frontier to use Omni's formatting, I would be so happy.)

Lately I've been working on a very outline intensive project and now I want to work on it with other people. But, it really needs to be an active outline with expanding and collapsing sections.

I discovered that I could export the outline from Omni into OPML, the basic data structure Dave uses for Fargo. I copied the OPML into the Dropbox file Fargo uses and, boom!, I had Fargo functionality.

To my eye, it was ugly but it turns out that Dave did a BEAUTIFUL THING. He made it so that you can execute Javascript from the outliner. No kidding. You just type some JS into the outline, hit cmd-/ and it runs.

Here's what I did:

$('body').prepend("<script src='http://static.tqwhite.org/iepProject/formatFargo.js'>");


That's right, I loaded a chunk of JS from my static server. That code changes this:



to look like this..



It took a fair amount of reverse engineering to figure it out but, it works like a charm.


Here's the code:

(I think the colorized picture is easier to read.)


And here it is if you want to do your own colorizing:


var colorize = function() {
    $('.concord .concord-node .concord-wrapper .concord-text').css({'font-family': 'sans-serif'});
    $('.concord-level-1-text').css({'color': 'black'});
    $('.concord-level-2-text').css({'color': '#664F58'});
    $('.concord-level-3-text').css({'color': '#456D72'});
    $('.concord-level-4-text').css({'color': '#AD9470'});
    $('.concord-level-5-text').css({'color': '#D3AF74'});
    $('.concord-level-6-text').css({'color': '#90967E'});

    $('.concord-level-7-text').css({'color': '#778'});
    $('.concord-level-8-text').css({'color': '#788'});

    $('.concord .concord-node > .concord-wrapper').css({'background': 'white'});
    $('.concord .concord-node.selected > .concord-wrapper').css({'background': 'rgb(245,250, 250)'});
    $('.concord .concord-node.selected').find('li .concord-wrapper').css('background', 'rgb(245,250, 250)')
}

$('body').bind('keyup', colorize);
$('body').bind('click', colorize);

colorize();

document.styleSheets[0].insertRule(".selected { background:rgb(245,250, 250); }", 0);
document.styleSheets[0].insertRule(".selected div { background:rgb(245,250, 250); }", 0);
document.styleSheets[0].insertRule(".selected div { color:normal; }", 0);
document.styleSheets[0].insertRule(".selected i { background:rgb(245,250, 250); }", 0);







Reinstalling NodeJS and npm

Recently, I upgraded to the latest NodeJS/npm and npm stopped working. It turns out that there was a problem with the OSX installer.

After painful amounts of googling, I found that some had solved it by "tracking down" the node and npm files, removing them and then reinstalling with the node distribution download (dmg) from nodejs.org.

I tracked down the files. Do this:


sudo rm -rf /usr/local/bin/node

sudo rm /usr/local/bin/npm

sudo rm -rf /usr/local/lib/node_modules/npm


And then hit up http://nodejs.org for a new installer. You will have a fresh working installation.


PS, the problem with npm was this:

When I typed

npm init

to start up a node module, I got errors that included

Error: Cannot find module 'github-url-from-git'

Turns out that basically everything I did with npm except --version was broken in this way.

The 'delete before reinstalling' process listed above fixed it.







Visual Studio 2015, .NET 5 rc1, dnu restore, asp.net missing (I can't believe it either)

It's been a half dozen years since I started a new project in Visual Studio. I was a little excited at the prospect. I like learning things and I know a lot about almost all the rest of the internet development topics.

I looked up the latest stuff and it turns out that we have a new Visual Studio and a new .NET that have taken a lot of good lessons from the rest of the world of web development. .NET 5 is out of beta and into Release Candidate 1. That's good enough for me. I expect the bugs will be small.

Wait. It's Microsoft and everything they do is stupid.

Problem Zero (which I won't detail)

I actually went through fits trying to get it all installed and looking good, but, having done that, I create a new project: ASP Web Application/ASP.NET 5 Web Application.

Problem One:

I have to do this twice. I keep code on an external drive that the file dialog navigates to as //psf.stuff... . It tells me I that "UNC paths are not supported." The second time, I typed (not navigate) the volume letter, "X:", and it worked.

Problem Two:

I build the solution. I get a bazillion (well, 204) errors. The first one tells me that "The type or namespace name 'Identity' does not exist in the namespace "Microsoft.AspNet'". Another, "The type or namesspace name 'AspNet' does not exist in the namespace 'Microsoft'". Can you imagine?

The project listed in the first error says "TestProject.DNX 4.5.1, TestProject.DNX Core 5.0" (obviously, the 'TestProject' is my project name). For the second one, it's "DNX 4.5.1" only.

I try using Nuget to add "Identity.Core" and it changes things. I screw around with that for awhile as new missing references appear until I start getting messages telling me that I have duplicate definitions. This is truly awful. (Did I mention that Microsoft always does it stupid? The package manager doesn't make sure the references are correct? Really?)

Problem Three:

I start over and this time I decide that I'm working toward .NET 5.0 so to hell with 4.5.1. I edit the project.json file and remove it. Build takes forever and I pretty much expect everything will blow up but instead, I get a message, "Dependencies in project.json were modified. Please run "dnu restore" to generate a new lock file."

This feels like progress. I right-click on the project, choose Open Command Line and type "dnu restore". It works. I return to VS and build again. It instantly repeats the exact same message. I delete the lock file and restore it. Same thing. A complete, stupid dead end.

THE SOLUTION (and a lesson is the complete depth of Microsoft stupidity)

I reverse the order of the references to 4.5.1 and 5.0 so that 5.0 comes first. IE,

I change from this:



to this:



The build succeeds promptly. Clicking the IIS Express button opens a web browser and shows me the scaffold web page.

This has taken me over 2.5 hours. Certainly, my inexperience with this technology made it slower. Someone better might have done it more quickly. However, this is the scaffold. This is the part that supposed to save time. This is an epic fail on Microsoft's part. I mean, they put the dependencies in the scaffold in the wrong order!!

The good news is that, if I got enough Google-friendly text in this page, you might have found it well before 2.5 hours elapsed.

Of course, that just means you need to endure Microsoft's next awful surprise. Good luck. I know I need some.



Bash List of Files in Directories with Complete Paths

I don't want to forget this and it took me too much googling to find.

find $PWD -type f | grep xsd

gets:

/..absolute path../Collections.xsd
/..absolute path../Composite/SIFNACompositeObjects.xsd
/..absolute path../Entity/SIFIdentityManagement.xsd
/..absolute path../Report/SIFNAassessmentSummary.xsd
/..absolute path../SIFglobal.xsd

Note that it is looking inside folders.


(Too much googling but, thanks StackOverflow: http://stackoverflow.com/questions/246215/how-can-i-list-files-with-their-absolute-path-in-linux)

NodeJS Express Body-Parser Post Data Missing Problem

I am amazed that NodeJS' main network server package, Express, does not handle Post data on its own. I just don't get it. It requires a package called Body-Parser.

I copied in the sample code from the Express website

http://expressjs.com/4x/api.html#req.body

got the required packages and made a little form to test it.

It did not work.

The docs explain that Body-Parser builds a request.body that contains the post data but it was empty. It did exist, but it was empty.

I did one million things to make sure that I was doing what I thought I was doing. Postman? Check. Curl? Check. Inch by inch inspection of my entry page? Check.

I got to looking at the post on the way into the page in Firebug. I noticed that the encoding that Firefox was using was

application/x-www-form-urlencoded

The Body-Parser docs say that any of their decoders will take a type parameter to specify this. I found an example and tried it out:

{type:'application/x-www-form-urlencoded'}

Nope. I tried this in some decoder called raw(), the urlencoded() one, I even put in into json() just in case. Nada.

At my wits end, I'm just trying things in Postman. I tell it to encode it in various ways and, Voila!!, when I choose

multipart/form-data

It works.

WTF? I think. Everything specifically tells me that Body-Parser SPECIFICALLY DOES NOT DO MULTIPART form data.


How much clearer could it be?

Then I realize, the sample code from the Express docs caused me to install (last night when this nightmare began) something called Multer. Experimentation tells me that this is the reason I can do multipart/form-data. Without Multer, I get nothing.

But, without Multer, I get nothing no matter what I do. I did everything I have tried before and could not get Body-Parser to work. With Multer, only multipart/form-data. Without, nothing.

If anyone can enter a comment telling me how I got this wrong, I would be grateful.


UPDATE: It was none of the above!!!


It turns out that, in the course of the above screwing around, I moved the assignment of the router to follow the assignment of the Body_Parser. It executes the router before the parser if you tell it to. I had inserted the new body-parser code after the route. No reason, it just happened .

app.use(bodyParser.urlencoded({ extended: true }))

must precede

app.use('/', router);


“This project is incompatible with the current version of Visual Studio”

Nice error message Microsoft. Why not just say, "Screw off. We don't care about your old projects." This is why I avoid them whenever possible.

However, in this case, it wasn't possible. It was some reference code for the protocol of a new thing I'm working on. It was done in Visual Studio 2013. I'm using Visual Studio 2015.

After doing a bunch of stuff that was totally useless (I am not very strong in .NET), I happened up on this simple solution...

Open the .csproj file in a text editor.

Change

12

to

14

Done.

Or, if you need more detail:

Change

<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

to

<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

After that it opened with no problem and I was able to build and use the project.

I have no idea what the ramifications of this could be in the long run. If I find any that are adverse, I will write it down here.




mysql: Load Data From and Select ... Into Outfile

Just so I don't forget...

I did a test of this.

select firstName, lastName from users into outfile 'tempTest9999'

Then, after creating an appropriate table...

load data infile 'tempTest9999' into table tempTest

The thing I don't want to forget is that the file was put into the directory...

/var/lib/mysql/DATABASENAME

The owner and group were both 'mysql'.

I know, it's what one would expect, but I forget these things.

Responsive Image Maps - Generator and jQuery Plugin

Bottom line, I need to do an image map in a responsive website.

First, I found this lovely image map generator. It is simple and works very well. It's good enough that I actually gave him a few bucks.

http://www.image-maps.com

The resulting <map> worked right away.

Then I started working on the real website. The image loads in a size relative to the browser window's size. The image map was out of alignment. I quickly realized the problem and googled Responsive Image Maps.

I found this:

https://github.com/stowball/jQuery-rwdImageMaps

I groaned. I hate adding dependencies and even more, I hate figuring out how to work new stuff that I'm probably not going to use again (this is the first image map I've used in years and once this project ends, probably the last for a long time). But, I did it.

The learning curve was ZERO.

I added the plugin. Copied his sample initialization and it worked perfectly the first time.

Win!!