Can not read data from local MongoDB using expressjs mongoose library - node.js

I am learning Mongoose and MongoDB and try to read data from a local hosted MongoDB, I typed similar example from Mongoose documentation. But it doesn't work.
I create a simple MongoDB collection named blogs inside a database called personal_website for test purposes. And there is only one document in this collection
personal_website> db.blogs.find()
[ { _id: ObjectId("63bbcb27ae437ded486fecf4"), title: 'test' } ]
There is my code which doesn't work
user#user-machine: ~$ cat server.js
const mongoose = require("mongoose");
mongoose.set("strictQuery", true);
mongoose.connect("mongodb://localhost/personal_website", () => {
console.log("connected to databse personal_website");
});
let blogSchema = new mongoose.Schema({
title: String,
});
let Blog = mongoose.model("blog", blogSchema);
let blogCount = Blog.find({}).count();
console.log(blogCount);
I run node server.js but I got this output:
Query {
_mongooseOptions: {},
_transforms: [],
_hooks: Kareem { _pres: Map(0) {}, _posts: Map(0) {} },
_executionStack: null,
.........
connected to databse personal_website
I expect get the similar result as i run db.blogs.find().count() command in MongoDB shell. How could I fix that? Should I query database after the connection established? I saw a lot of tutorials connect to their MongoDB at the very beginning just like me and also the documentation says "Mongoose lets you start using your models immediately, without waiting for mongoose to establish a connection to MongoDB". So can you guys help me figure out what cause this problem and how to fix it? I really appreciate that, I stuck there like four hours.

use port number and 127.0.0.1 in your connection string:
"mongodb://127.0.0.1:27017/personal_website" instead of "mongodb://localhost/personal_website" (27017 is default port)
try to wrap your query with async function and use await:
async function count() {
let blogCount = await Blog.find({}).count();
console.log(blogCount);
}
count();

Related

Unable to Connect to the MongoDB Database

Using the MongoDb and Mongoose for the first time to store the data of my app.js file. When I run the app.js then it throws this error after a while -> MongooseError: Operation peoples.insertOne() buffering timed out after 10000ms.
import mongoose from "mongoose";
mongoose.set("strictQuery", false);
mongoose.connect(
"mongodb://localhost:27017/peopleDB",
{ useNewUrlParser: true },
(err) => {
if (err) console.log(err);
else console.log("MongoDB is connected");
}
);
const peopleSchema = new mongoose.Schema({
name: String,
age: Number,
});
const People = new mongoose.model("People", peopleSchema);
const people = new People({ name: "John", age: 37 });
people.save();
this is the code that I wrote
After a lot of searching for the solution got to know that the connection was not made, if you are using the node the latest node.js version then replace the "localhost" with "127.0.0.1" and then try running the app.js
Create model name as "person", since people is already plural, and it may cause an error.
And make sure you run mongod server in the background using git

Mongoose updateMany with aggregation pipeline

MongoDB supports updates with aggregation pipelines (https://docs.mongodb.com/manual/tutorial/update-documents-with-aggregation-pipeline/).
Here is sample query(https://mongoplayground.net/p/i7A4YoIhyS5).
The update function takes an array (the pipeline) as the second argument.
In Mongoose however, it turns out you can pass only an object (by the docs https://mongoosejs.com/docs/api.html#model_Model.updateMany, also I have tried myself and array is not supported). Are there any ways to use Updates with aggregation pipelines in Mongoose?
Mongoose has not implemented a convenience wrapper for that just yet.
However, Model.collection provides read-only access to the underlying collection object from the native driver, including its methods.
Instead of Model.updateMany(), try using Model.collection.updateMany(), which should use the syntax described for the MongoDB Node.JS driver
Edit
Ugly demo code using Mongoose 5.12 and MongoDB 4.2:
const mongoose=require('mongoose');
const testSchema = new mongoose.Schema({ test:String });
const testModel = mongoose.model('testModel',testSchema);
mongoose.connect('mongodb://localhost/test', {useNewUrlParser: true, useUnifiedTopology: true});
async function main() {
const doc = new testModel({test:"testString"});
await doc.save();
const result = await testModel.collection.updateMany({},[{$set:{updated:{$concat:["$test",{$toString:"$_id"}]}}}]);
console.log("matchedCount:",result.matchedCount);
console.log("modifiedCount:",result.modifiedCount);
const newdoc = await testModel.findOne({});
console.log(newdoc);
process.exit();
}
main();
Output from the above:
matchedCount: 1
modifiedCount: 1
{
_id: 606945d4d5a5d9bec9038a59,
test: 'testString',
__v: 0,
updated: 'testString606945d4d5a5d9bec9038a59'
}

Mongoose save fail without error

I got success message, without document creation.
var mongoose = require('mongoose');
mongoose.Promise = global.Promise;
var conn = mongoose.createConnection(mongodb://localhost:27017/social_media);
var testModel = conn.model('test', new mongoose.Schema({
key: { type: String, required: true }
}));
var test = new testModel();
test.key = 'hello';
test.save().then(function(tmp) {
console.log('success');
console.log(tmp);
}).catch( function() {
console.log('failure');
});
As a result I get in console 'success' message with created object - so as I assume, document should be successfully inserted. In the moment of code run, database and collection don't exist. After code run, only db is created.
I tried to change 'createConnection' to 'connect' without any result.
I have already checked plenty of similar answers, but still can't find solution.
I'm using MongoDB v3.2.8, node.js MongoDbDriver v2.2.5 and Mongoose v4.5.8
The fault was in used GUI. I was using RoboMongo v0.8.5 and MongoDb v.3.2.8. The problem is that RoboMongo in that version is not supporting used MongoDb version. The full suport for mongo 3.x, came with RoboMongo v.0.9.0 - http://blog.robomongo.org/robomongo-rc1-with-full-support-for-mongodb-3/

The records can be inserted in the db and can be fetched (with mongoose), but when I log into the mongodb, it is empty

I am following this tutorial to understand how mongoose interacts with mongodb: http://blog.modulus.io/getting-started-with-mongoose
I have created a schema and a model. When I save the data, I get a console callback, that gives me out everything, I have saved. When I find the information, it also gets logged out. But when I log into mongo via terminal, use the mydb and execute the query db.mydb.find().pretty(), I get no results.,
What might be the problem? I am using exactly the same code, as in the tutorial.
This is the code, in case it will help to find the problem, somehow:
This is in the app.js
var db = mongoose.connection;
// console errors
db.on('error', console.error);
// load models
db.once('open', function() {
fs.readdirSync(__dirname = './models/').forEach(function(filename) {
if(~filename.indexOf('.js')) {require('./models/' + filename)};
});
});
mongoose.connect('mongodb://localhost/mydb');
*So it basically creates the connection, loads all of the models from the folder and consoles an error, if it occures (it does not).
Here is the code from my user model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var usersSchema = new Schema({
name: String,
age: Number,
admin: Boolean
});
var User = mongoose.model('Users', usersSchema);
Here I insert the user:
var danny = new User({
name: 'Danny',
age: 25,
admin: true
});
danny.save(function(err, res) {
if (err) { return console.error(err) };
console.dir(res);
});
*It logs out this user, when saved.
If I find all the users, I get the list of the same user (because It was accidentally saved multiple times). To find all, I use this command:
User.find(function(err, res) {
console.dir(res);
});
If I log in mongodb using command mongo on my Ubuntu Linux, and then I switch to the database with command use mydb and then db.mydb.find().pretty() It prints out nothing
You are making a small mistake when querying the database through the Mongo shell. Instead of using db.mydb.find().pretty(), you should use db.users.find().pretty().
Here is why:
You are connecting to your database with this line in Mongoose:
mongoose.connect('mongodb://localhost/mydb');
The mydb at the end will be the name of your database. So you might want to change this to something else so it is easier to recognise the database in the future.
In the Mongo shell, you are switching your database correctly using use mydb. To query your collection, you will need the following syntax:
DB + collection name + command() + extra stuff();
This means you will get the following command:
db.users.find().pretty();
The reason you should be using users, is because of this line:
var User = mongoose.model('Users', usersSchema);
Users will be the name of your collection. Please note that if you used User, Mongoose would have added an "s" to your collection name. To overwrite this, you can use this line:
usersSchema('collection', 'user');
Now your collection will always get the name user.

Pass mongoose connection to module

I'm writing a Node module which whould perform queries to MongoDB.
My module should take as parameter (when I init it with new MyModule(db)) the MongoDB connection and use it inside it.
I was using standard MongoDB without any NPM module and I was passing in my db variable the connection to MongoDB. Now I'm switching to Mongoose and I can't find a way to pass the Mongoose connection to my module.
I don't want to initialize the Mongoose connection inside my module because I want to share it with my tests and with other modules.
How can I do? I've tried passing mongoose to my module but it doesn't work "is not a function".
Edit:
After reading the reply of #Neil Lunn I'm posting this sample of my module:
(function () {
"use strict";
/**
* various requires
*/
function TopicManager(dbURI) {
if (!(this instanceof TopicManager)) { return new TopicManager(dbURI); }
mongoose.connect(dbURI);
}
TopicManager.prototype.save = function (topics, done) {
var Topic = new mongoose.schema(
{
title: { type: String },
slug: { type: String, index: { unique: true } }
},
{collection : "topics"}
);
/**
* Use monguurl on "slug"
*/
mongoose.update(
{title: topic.title},
{upsert: true},
function (err, numberAffected, raw) {
if (err) { return done(err); }
return done(null, raw);
}
);
};
module.exports = TopicManager;
})();
It doesn't work because when I use it I get undefined is not a function when it runs new mongoose.
Generally speaking you don't do this. The mindset is a little different with mongoose than working with the native driver in it's raw form, and there are plenty of things helping under the hood to make things work a bit more seamlessly without diving into the gory details.
So the basic approach is when you define your "schema" and "models", these are bound to the default connection instance. Unless you have a specific reason for binding to another connection, this is what you should follow:
So you would have a Schema and model definition:
var mySchema = new Schema({
"name": String
});
module.exports = mongoose.model( "Model", mySchema, "collection" )
Where the "collection" part is optional otherwise the "model" name in the first argument is put to standard rules, usually lowercase and pluralized.
Then in your other code listing, you pull this in with require:
var Model = require('./models/mymodel.js');
And use your model objects as mongoose permits:
Model.find({ "field": "name"}, function(err,models) {
});
So it allows a bit more abstract handling than is done with the basic driver as the "models" themselves know how to bind to connections, or are otherwise explicitly bound to the connection you want as an optional parameter.
You can create a default Mongoose connection:
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test');
var db = mongoose.connection;
If you want to open multiple connections you can use createConnection:
var dbconnection = mongoose.createConnection ('uri,uri');
This connection object can then be used for creating/retrieving models that are scoped only to this connection.
The Mongoose connection object has multiple events on which you attach handlers. You should check out the documentation for the full list of handlers you can use.
To get you started, a basic approach would be:
// log connection errors
db.on('error', console.error.bind(console, 'connection error:'));
// wait for opening the connection
db.once('open', function () {
// do something once connection to the MongoDB is open
});
If you open your connection using createConnection, you need to use it when creating models:
// dbconnection is created using createConnection
var MyModel = dbconnection.model('MyModel', MyModelSchema);

Resources