I can't seem to find how to log into a database in my FeathersJS app.
I would prefer to specify database info and login info in the service, but I just need it to work.
In myApp/config/default.json there is the following line:
"postgres": "postgres://postgress:#localhost:5432/feathers_db",
at:
http://docs.sequelizejs.com/en/latest/docs/getting-started/
It says that a string like the above should be:
"postgres": "postgres://username:user_password#localhost:5432/feathers_db",
But this does not work. It is also not very Feathers-like as now I am locked into one postgress db for all my postgress transactions.
In services/index.js there is the following line:
const sequelize = new Sequelize(app.get('postgres'), {
dialect: 'postgres',
logging: false
});
I could customize the above line to be what Sequelize says to do in their guide and have username and password as an argument, but then why is the template not already laid out like this?
There is also this line:
app.set('sequelize', sequelize);
If I have several postgress databases what do I do? DO I make new Sequelize objects and do something like:
app.set('sequelize_db1', sequelize_db1);
app.set('sequelize_db2', sequelize_db2);
Or do I specify db info, including user info in the service's model?
What does the logging in process for Postgress look like if one is using the generic db language rather than sequelize?
So in a word "yes". Everything I asked in my question was yes.
I can connect to the db like shown in the sequelize documentation. I can also configure the config.json file to have a "postgres" configuration with my user and db name. I could also place the full path in the services/index.js file when creating the new sequelize object. The best way to check that there is a connection is to have the following code after creating the new sequelize object:
new_sequelize_object
.authenticate()
.then(function(err) {
console.log('Connection to the DB has been established successfully.');
})
.catch(function (err) {
console.log('Unable to connect to the database:', err);
});
(taken from: http://docs.sequelizejs.com/en/latest/docs/getting-started/)
one can also define several sequelize objects and set them in the app. Then when defining the model in the specific service's index.js file, place the new bound name in the app.get('new_sequelize_object').
Here is the services/index.js file with two databases defined:
'use strict';
const service1 = require('./service1');
const authentication = require('./authentication');
const user = require('./user');
const Sequelize = require('sequelize');
module.exports = function() {
const app = this;
const sequelize = new Sequelize('feathers_db1', 'u1', 'upw', {
host: 'localhost',
port: 5432,
dialect: 'postgres',
logging: false
});
const sequelize2 = new Sequelize('postgres://u1:upw#localhost:5432/feathers_db2', {
dialect: 'postgres',
logging: false
});
app.set('sequelize', sequelize);
app.set('sequelize2', sequelize2);
sequelize
.authenticate()
.then(function(err) {
console.log('Connection to sequelize has been established successfully.');
})
.catch(function (err) {
console.log('Unable to connect to the database:', err);
});
sequelize2
.authenticate()
.then(function(err) {
console.log('Connection has been established to sequelize2 successfully.');
})
.catch(function (err) {
console.log('Unable to connect to the database:', err);
});
app.configure(authentication);
app.configure(user);
app.configure(service1);
};
And here is the service1/index.js file that uses service sequelize2:
'use strict';
const service = require('feathers-sequelize');
const service1 = require('./service1-model');
const hooks = require('./hooks');
module.exports = function(){
const app = this;
const options = {
//Here is where one sets the name of the differeng sequelize objects
Model: service1(app.get('sequelize2')),
paginate: {
default: 5,
max: 25
}
};
// Initialize our service with any options it requires
app.use('/service1', service(options));
// Get our initialize service to that we can bind hooks
const service1Service = app.service('/service1');
// Set up our before hooks
service1Service.before(hooks.before);
// Set up our after hooks
service1Service.after(hooks.after);
};
Related
const dotenv = require('dotenv').config();
const Op = require('sequelize').Op;
//logger here
const Product = require('../models/product');
const MainCourse = require('../models/main_course');
const Drink = require('../models/drink');
const SideDish = require('../models/side_dishes.js');
const Sequelize = require('sequelize');
var database;
var username;
var password;
var host;
if (process.env.NODE_ENV !== 'production') {
database = process.env.DB_TABLE;
username = process.env.DB_USER;
password = process.env.DB_PASS;
host = process.env.DB_HOST;
}
const sequelize = new Sequelize(
database,
username,
password,
{
dialect: 'postgres',
host: host,
pool: {
max: 40,
min: 0,
idle: 20000000,
acquire: 100000000,
},
logging: console.log
}
);
sequelize
.authenticate()
.then(async () => {
sequelize.sync({force: true, logging: console.log}).then(() => console.log('Synced DB'))
console.log('Connection with Sequelize established successfully.');
})
.catch(err => {
console.error('Unable to connect via Sequelize:', err);
});
When I run this file through the terminal my result is:
Executing (default): SELECT 1+1 AS result
Connection with Sequelize established successfully.
Executing (default): SELECT 1+1 AS result
Connection with Sequelize established successfully.
Executing (default): SELECT 1+1 AS result
Synced DB
Why is the database not actually syncing even when the model files are imported? I'm trying to create a seed file where the database is dropped entirely before data is seeded. I want to authenticate the database connection and then drop all tables before recreating them, and then adding the fake data. How do you make the database sync immediately after authenticating the connection?
I just pulled a project to a new machine, I use PostgreSQL for my DB, sequelize as an ORM, and feathersjs and express or middleware. I try to start the project as I always do but it doesn't work.
I have an .env file with all my environment configuration info, what I usually do is first run sequelize db:create, to create the DB, after that, I use npm start to create the tables. However when I do it it doesn't create any table or show any error, it just shows the info: Feathers application started on http://localhost:3030 but when I open pgAdmin the Database is empty. I tried logging in in sequelize but it's not showing anything at all. I also deleted the ENV and it doesn't show any error at npm start (it does show an error at sequelize db:create. This is driving me nuts.
Heres my sequelize.js:
require('dotenv').config();
const Sequelize = require('sequelize');
const { Op } = Sequelize;
const operatorsAliases = {
// ...
};
module.exports = function (app) {
const connectionString = `postgres://${process.env.DB_USERNAME}:${process.env.DB_PASSWORD}#` +
`${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_NAME}`;
const sequelize = new Sequelize(connectionString, {
dialect: 'postgres',
dialectOptions: {
ssl: false
},
logging: console.log,
operatorsAliases,
define: {
freezeTableName: true
}
});
const oldSetup = app.setup;
app.set('sequelizeClient', sequelize);
app.setup = function (...args) {
const result = oldSetup.apply(this, args);
// Set up data relationships
const models = sequelize.models;
Object.keys(models).forEach(name => {
if ('associate' in models[name]) {
models[name].associate(models);
}
});
// Sync to the database
sequelize.sync({ logging: console.log });
return result;
};
};
My npm start script just points to an app.js file where I just import sequelize with app.configure(sequelize);
You may need to run sequelize db:migrate after creating the database
So it turns out is actually an issue with node 14. I had to install a newer version of node-Postgres (pg#8.0.3) as pointed out in here
In the example I am working with is this code:
//lets require/import the mongodb native drivers.
var mongodb = require('mongodb');
//We need to work with "MongoClient" interface in order to connect to a mongodb server.
var MongoClient = mongodb.MongoClient;
// Connection URL. This is where your mongodb server is running.
var url = 'mongodb://localhost:27017/my_database_name';
// Use connect method to connect to the Server
MongoClient.connect(url, function (err, db) {
if (err) {
console.log('Unable to connect to the mongoDB server. Error:', err);
} else {
//HURRAY!! We are connected. :)
console.log('Connection established to', url);
// Get the documents collection
var collection = db.collection('users');
//Create some users
var user1 = {name: 'modulus admin', age: 42, roles: ['admin', 'moderator', 'user']};
var user2 = {name: 'modulus user', age: 22, roles: ['user']};
var user3 = {name: 'modulus super admin', age: 92, roles: ['super-admin', 'admin', 'moderator', 'user']};
// Insert some users
collection.insert([user1, user2, user3], function (err, result) {
if (err) {
console.log(err);
} else {
console.log('Inserted %d documents into the "users" collection. The documents inserted with "_id" are:', result.length, result);
}
//Close connection
db.close();
});
}
});
As you may see, he is doing an operation in the connect function. I would like to keep it modular and separate the connection from DB operations.
My suggestion would be to make a singleton on db variable and reuse that one. At least that's what I would do in Java to which I am used to.
However, I am not sure as in the example he hasn't suggested anything like that.
I would recommend against maintaining one connection if you want any kind of scalability.
There are a number of options for connection pooling, etc, but most folks who spend any time at all with Node and MongoDB end up moving to Mongoose at some point.
In addition to adding a nice schema layer, it offers connection abstraction so that you can default to a shared connection by calling mongoose.connect(), or you can create multiple connections or participate in connection pooling by calling mongoose.createConnection(). In both cases, you call it without a callback, and the mongoose machinery will defer subsequent calls to the module until after the connection is established, so that your code doesn't have to care.
Something like your use case might look like so:
// in your app.js or server.js file
var mongoose = require('mongoose');
mongoose.connect(config.db.url); // assuming you have some module that handles config variables
Then in ./models/user.js
const mongoose = require('mongoose'),
Schema = mongoose.Schema;
const UserSchema = new Schema({
name: String,
age: Number,
roles: [String]
});
mongoose.model('User',UserSchema);
finally, in lets say a seed function to create your initial batch of users:
const mongoose = require('mongoose'),
User = mongoose.model('User');
// create some users
var user1 = new User({name: 'modulus admin', age: 42, roles: ['admin', 'moderator', 'user']});
var user2 = new User({name: 'modulus user', age: 22, roles: ['user']});
user1.save(console.log);
user2.save(console.log);
I believe maintaining a single connection is the best as mentioned in another thread:
The primary comitter in node-mongodb-native says
You open do MongoClient.connect once when your app boots up and reuse the db object. It's not a singleton connection pool each .connect creates a new connection pool. So open it once an[d] reuse across all requests.
Say on server start initiate the mongo connection.
Server.js:
...
var db = require('./db');//require db.js
db.openMongoConnection(function(error)
{
if(error)
{
console.log(error);
console.log("cannot make the connection with database");
}
else
{
server.listen(7400);//say ur server listening on 7000 port
}
}
db.js
var db1;
var MongoClient = require('mongodb').MongoClient;
exports.openMongoConnection = function(callback)
{
MongoClient.connect(<YourUrl1>,function(err,dbInstance)
{
if(err)
{
callback(err);
}
else
{
db1 = dbInstance;
callback(null);
}
});
};
exports.getCollection = function(collectionName, callback){
dbInstance.collection(collectionName, function(err, collectionInstance){
if(err)
{
callback(err);
}
else
{
callback(null, collectionInstance)
}
});
}
Then you can call the getCollection to use at anytime by requiring dbInsance
I cant create my database 'sms-dev' in mongodb after starting the server but in my console it was printing connected to mongo successfully.I kept my db module inside models folder as db.js and export that module in another file(config.js) inside models folder
Here is the code in db.js file
var db = {
// Connects to mongoDB
connect: function(url, options) {
mongoose.connect(url, options);
mongoose.connection.on('open', function(){
console.log("Connected to mongo successfully");
});
mongoose.connection.on('disconnect', function(){
console.log("Mongo disconnected");
});
mongoose.connection.on('error',function (err) {
console.log('Mongoose default connection error: ' + err);
});
process.on('SIGINT', function() {
mongoose.connection.close(function () {
console.log('Mongoose default connection disconnected through app termination');
process.exit(0);
});
});
}
}
module.exports = db;
and my config.js file is
exports.database = {
url: 'mongodb://127.0.0.1:27017/sms-dev',
options: {
db: { native_parser: true,safe:true },
server: { poolSize: 10 }
}
}
I connected this db in server.js as
var dbcon = process.env.MONGOLAB_URI || config.database.url;
db.connect(dbcon, config.database.options);
This line:
As soon as you create a record with that connection
From this answer.
Did it for me. In my case I had to manually:
Create the database
Create a collection
Create a record in the collection
And then everything was good again.
You should keep your db connection very simple as you are using mongoose.
mongoose.connect should only be called once. That will create the default connection pool for your application.
//db.js
// Bring Mongoose into the app
var mongoose = require( 'mongoose' );
// Create the database connection
mongoose.connect('mongodb://127.0.0.1:27017/sms-dev');
// CONNECTION EVENTS
// When successfully connected
mongoose.connection.on('connected', function () {
console.log('Mongoose default connection open to ' + 'mongodb://127.0.0.1:27017/sms-dev');
});
// If the connection throws an error
mongoose.connection.on('error',function (err) {
console.log('Mongoose default connection error: ' + err);
});
// When the connection is disconnected
mongoose.connection.on('disconnected', function () {
console.log('Mongoose default connection disconnected');
});
// If the Node process ends, close the Mongoose connection
process.on('SIGINT', function() {
mongoose.connection.close(function () {
console.log('Mongoose default connection disconnected through app termination');
process.exit(0);
});
});
You can then easily use the db connection by require mongoose in your files.
//users.js
var mongoose = require( 'mongoose' ),
Users = mongoose.model('users');
It seems that my mongodb was not locked properly so i remove the mongodb.lock file and run with -repair option
Once you ll save data in the database
,You can see the Database by running command
show dbs
const mongoose=require("mongoose")
mongoose.connect('mongodb://localhost:27017/username_db');
var db=mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
console.log("connected successfully")
});
const Schema=mongoose.Schema;
const myschema=new Schema({
name:String,
},{
timestamps:true
});
var model=mongoose.model('myname',myschema);
var data=new myname({
name: 'xyz',
})
data.save((err)=>{
res.send("Error in saving to database");
})
Once you ll save data in the database
,You can see the Database by running command
show dbs
const mongoose=require("mongoose")
mongoose.connect('mongodb://localhost:27017/username_db');
var db=mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
console.log("connected successfully")
});
const Schema=mongoose.Schema;
const myschema=new Schema({
name:String,
},{
timestamps:true
});
var model=mongoose.model('myname',myschema);
var data=new myname({
name: 'xyz',
})
data.save((err)=>{
res.send("Error in saving to database");
})
This is quite old Post, to which I am updating using latest packages - This solution will fix this mongo db connection issue on following version of env.
Node version - 11.5.0 (node -v)
NPM. - 6.4.1(npm -v)
Typescript. - 3.8.3(tsc -v)
Mongodb. - 5.9.15 (package.json)
Following are the steps need to take care in order to fix this -
1. First of all verify all changes in .ts file will be reflecting changes in corresponding .js file. As it was issue with my code it was not being updated.
Run following command and verify .js file
tsc --build tsconfig.json
If js file is not being updated simply delete.js file and run above command. It's pretty simple fix but some time we overlook for it.
Since it's typescript code. So need to copy past below code for verification.
Import * as m from 'mongoose';
export class UserControl {
RegisterUser(){
Const uri = "mongodb://127.0.0.1:27017/User";
m.connect(uri,
{useNewUrlPaerser:true,
useUnifiedTopology:true,
useFindAndModify:true,
useCreateIndex:true });
Let db = m.connection;
Db.once("open",async() =>.
{console.log(connected)});
Db.once("error",async() =>
{console.log(error)});
Const userSchema = new m.schema({
FirstName:string,
Last name:string
});
Const User = m.model('users', userSchema);
Const user = new User({
FName:Andy,
LName:Pat });
Const result = await user.save();
Console.log(result);
}
Run your solution by npm start.
Verify if db collection created?
If not.
First create db with name as "User" in mongodb
Using mongo db compass.
And than try. Still not able to see the collection.
Now need to start two separate console terminal.
go to folder and executive mongo
c:\program file\MongoDb\server\4.2\bin> mongo.exe
on another terminal type mongod ,
it will start your mongo Damon.
Now try. Since this above step will stable connection and show 1 connection active.
Hope this update help.
If you are using Mongoose or MongoClient to connect the mongodb database you will see the database created after you save the first document to the database.
e.g.: the below code will only show connection was successful but it does not create the database 'mydb'
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/mydb')
.then(() => console.log('Connected to MongoDB...'))
.catch(err => console.error('Could not connect to MongoDB...', err));
The databse 'mydb' is created only when you save first document record.
const courseSchema = new mongoose.Schema({
name: String,
author: String,
tags: [String],
date: {type: Date, default: Date.now},
isPublished: Boolean
});
const Course = mongoose.model('Course', courseSchema);
async function createCourse(){
const course = new Course({
name: 'Some Course',
author: 'My Name',
tags: ['JavaScript', 'backend'],
isPublished: true
});
const result = await course.save();
console.log(result);
}
createCourse();
This is a duplicate of:
Mongo db that does not exist but shows up in connection
If you insert data your database will be created.
There are some similar questions but all of them involves using the MongoDB NodeJS driver instead of Mongoose ODM.
I read the docs but couldn't find such functionality.
You can't directly get the list from the connection provided by mongoose, but it's easy to do with the mongo Admin object as it contains a function called listDatabases:
var mongoose = require('mongoose')
, Admin = mongoose.mongo.Admin;
/// create a connection to the DB
var connection = mongoose.createConnection(
'mongodb://user:pass#localhost:port/database');
connection.on('open', function() {
// connection established
new Admin(connection.db).listDatabases(function(err, result) {
console.log('listDatabases succeeded');
// database list stored in result.databases
var allDatabases = result.databases;
});
});
A very modern approach to get list of all mongo databases using mongoose (version 6.10.*) is to Create a mongoose connection to connect to Mongo's admin database and make sure you have an admin user.
Mongoose object is a very complex object. To list the db's :
const connection = `mongodb://${encodeURIComponent(username)}:${encodeURIComponent(password)}#${hostname}:${port}/admin`
mongoose is a very complex object with promises for executing several functions. to list the db's :
mongoose.connect(connection, { useNewUrlParser: true , useUnifiedTopology: true }).then( (MongooseNode) => {
/* I use the default nativeConnection object since my connection object uses a single hostname and port. Iterate here if you work with multiple hostnames in the connection object */
const nativeConnetion = MongooseNode.connections[0]
//now call the list databases function
new Admin(nativeConnetion.db).listDatabases(function(err, results){
console.log(results) //store results and use
});
})
Result:
{ databases:
[ { name: 'admin', sizeOnDisk: 184320, empty: false },
{ name: 'config', sizeOnDisk: 73728, empty: false },
{ name: 'local', sizeOnDisk: 73728, empty: false },
{ name: 'test', sizeOnDisk: 405504, empty: false } ],
totalSize: 737280,
ok: 1 }
If someone is looking for answers from the latest version of Mongoose and Mongodb, the below code can be used.
import mongoose from 'mongoose';
mongoose.set('strictQuery', true);
mongoose.connect('mongodb://localhost:27017/mydb', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const db = mongoose.connection;
// Check DB Connection
db.once('open', () => {
(async () => {
const data = await mongoose.connection.db.admin().command({
listDatabases: 1,
});
console.log(data);
})();
console.log('Connected to MongoDB');
});
// Check for DB errors
db.on('error', (err) => {
console.log('DB Connection errors', err);
});
export default mongoose;
If you want to get the database list on your other functions, make sure the connection is established first and also make sure the user has admin access and then just do the below query. This is a sample from my API router.
// Get all databases
router.get('/database/get', async (req, res) => {
try {
const data = await mongoose.connection.db.admin().command({
listDatabases: 1,
});
if (data && data !== null) {
res.status(200).send({ data: data });
return;
}
res.status(200).send({ data: null, message: 'Data not found' });
} catch (e) {
// eslint-disable-next-line no-console
console.log(e);
res.status(500).send(e.message);
}
});
Try running this code. Original take from Gist.