User.findOne() is not a function - javascript

passport.use('local-signup', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true // allows us to pass back the entire request to the callback
},
(req, email, password, done) => {
// asynchronous
// User.findOne wont fire unless data is sent back
process.nextTick(() => {
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
User.findOne({ 'email' : email },function(err, user){
// if there are any errors, return the error
if (err)
return done(err);
// check to see if theres already a user with that email
if (user) {
return done(null, false, {'errorMessages': 'That email is already taken.'});
} else {
// if there is no user with that email
// create the user
let newUser = new User();
// set the user's local credentials
newUser.name = req.body.fullname;
//newUser.email = email;
newUser.password = newUser.generateHash(password);
// save the user
newUser.save((err)=>{
if (err)
return done(err);
return done(null, newUser);
});
}
});
});
}));
The above code is in node js using passport js authentication and the code of local-signup is not working.
In the above code i am getting the error:
User.findOne() is not a function.
My schema is all right... please help

You need to (if you're not already) create instance of your data with a model like
var UserDetails = mongoose.model('userInfo', UserDetail);
Now you should be able to use .findOne here.
And make sure you're defining structure for your date inside a collection like..
var Schema = mongoose.Schema;
var UserDetail = new Schema({
username: String,
password: String
}, {
collection: 'userInfo'
});

Kindly, use the code below
module.exports = User = mongoose.model('user', UserSchema)
User should be the model name and remember to define const UserSchema = new Schema at the top to create a new model in MongoDB and
user should the route where you have the
router.post('/user') (req, res) => { code here }
with this, you are exporting the mongoose schema to the route user, this which enables findOne to be seen as a mongoose function.

maybe you did not export the Model from your User model folder.
eg:
module.exports = User = mongoose.model("users", UserSchema);

Export the user Model from models directory from file named user.js.
module.exports.User = User
Then Load User model from any other
const {User} = require('../models/user.js');
Note : I'm assuming user models file is named user.js

User.findOne is not a function error
In my case:
CORRECT SYNTAX:
const User = require('../../models/User') // rectified
Error occured due to VS code auto-format my import changed to below
const User = require - '../../models/User'
:- Though this import is the culprit, VS code still validated this import !

You can try this:
user.collection.findOne(...)

use
module.exports = User = mongoose.model("users", UserSchema);
instead of
module.exports = User => mongoose.model("users", UserSchema);

In my case the problem was that instead of writing the below code
module.exports = UserModel;
I had wrote
exports.module = UserModel;

It is how you export and import your Model. If you are defining model as const User = mongoose.model("users", UserSchema); then exporting it by export default User;. you should use the following to import that:
import User from '../db/models/user';
instead of
const User = require('../db/models/user');

TRY THIS
make sure you imported your schama as import User from '../db/models/user'; instead of const User = require('../db/models/user'); if you're using es6 syntax

If your error contains also something like Warning: Accessing non-existent property '...' of module exports inside circular dependency and TypeError: User.findOne is not a function, and generaly the model is an empty {}, then the problem may be the connection (import and export) of the both files. The file that exports the used model can most likely also import the destionation file where the model is used.
Example: Let us have 2 files, user - exporting the User model, and the receiver - example.js
user.js
const mongoose = require('mongoose')
const Schema = mongoose.Schema;
const exmple = require("./example"); //notice how the destination file is also imported in the sender model file
//... all your code and schema here
const User = mongoose.model('User', UserSchema);
module.exports = User;
example.js
const User = require("./user"); // circular dependency
//... your code
This mostly happens, as in my case, when having 2 model files, and importing, and exporting each one into another creating the error. I needed the export model for some User model functions.

I also had this situation where:
const User = require('../../mongoose/User');
User.findOne(...);
returned 'findOne is not a function'
But by changing to:
var User = require('../../mongoose/User');
User.findOne(...);
..it worked.
Hope I helped someone !

In my case I defined User like this ↓
const User = '../../models/User'
instead of ↓
const User = require('../../models/User')

Related

Cannot access 'user' before initialization

I am new in Mern development, and getting this "Cannot access 'user' before initialization" error in controller file
Controller/user.js
const user = require('../models/user')
exports.signup = (req,res)=>{
console.log('req.body', req.body);
const user = new user(req.body);
user.save((err, user)=>{
if(err){
return res.status(400).json({
err
})
}
res.json({
user
})
})
}
Route/user.js
const express = require('express');
const router = express.Router();
const {signup} = require('../controllers/user');
router.post("/signup", signup);
module.exports = router;
On line 1 you define a variable named user.
On line 4 you define a different variable also named user in a different scope.
At the other end of line 4 you try to call the value of that variable as a function, but it doesn't have a value yet. Hence the error message.
You intended to call the function in the variable from line 1, but since the one on line 4 shadows it, you are calling that instead.
Don't shadow your variables.
Change the name of one of them.

How to exports many mongoose models modules in node.js

I have 2 models like this
const Db = mongoose.model('db', dbSchema);
const Beacon = mongoose.model('beacon', dbSchema2);
Now I want to export them. First I export Db and everything is fine. I can do an HTTP request with it.
module.exports = Db;
However, when I try to export ´the 2nd one outside, it stops functioning. The functions below will return a blank JSON file as a response.
module.exports = Db;
module.exports = Beacon;
This won't work either. It returns an error handler saying all my functions in the handler is not function.
module.exports = {
Db, Beacon
}
This is the function on the file I import the models.
router.get('/data/:id', function(req, res, next) {
Db.findOne({ _id: req.params.id }).then(function(db) {
res.send(db);
});
}
The return from the handler is Db.findOne is not a function.
Is there any way to export them both? Thank you.
Here is the importing on another file
const Db = require('./db.js');
const Beacon = require('.db.js');
This should work:
Exporting in one file
module.exports = { Db, Beacon };
Then, importing in another file
const { Db, Beacon } = require('path-to-db.js');
// use them
Db.doSomething();
Beacon.doSomethingElse();
Notice that this uses the ECMAS 6 Destructuring Assignment (additional info on MDN)

OpenRecord: TypeError: User.create is not a function

ORM OpenRecord
I'm getting an error ( TypeError: User.create is not a function ) when I do the following:
await User.create(req.body.data)
When I log User I get this: [Function: User]
Database config:
//config/database/openRecord.js
/** more code above */
let store = new Store({
database,
user,
password,
host,
autoConnect: true,
autoAttributes: true,
models: require("../../app/models/models")
});
Models:
//app/models/models.js
module.exports = [
require("./user")
]
Model:
//app/models/user.js
const Store = require('openrecord/store/mysql');
class User extends Store.BaseModel {
static definition(){
this.validatePresenceOf(
'first_name', 'last_name', 'email', 'password'
);
this.validatesConfirmationOf('password');
this.validateFormatOf('email', 'email');
}
fullName(){
return `${this.first_name} ${this.last_name}`
}
}
module.exports = User;
Why is it throwing an error when I've clearly defined my object the correct way?
openrecord github link
openrecord website documentation
Two small typos are validatePresenceOf (should be validatesPresenceOf) and validateFormatOf (should be validatesFormatOf).
However, this is not the error you experience!
I'm pretty sure that you forget to wait until the store is ready.
If you use e.g. express I recommend to start listening after the store has loaded:
const express = require('express')
const store = require('./store')
const app = express()
async function start() {
// add middleware ...
await store.ready()
// start express server
app.listen()
}
start()
You have not exported the module. For example, we write:
module.exports = mongoose.model("user", userobj)
This is missing

Get middleware mount point from request in Express

I have an Express application with a router, here is the example of the router:
const router = require('express-promise-router')();
const users = require('./users');
const validate = require('./validate');
router.get('/users', users.list);
router.get('/users/:id', users.get);
// other routes here
module.exports = router;
Now I want to add a middleware that validates each query, like that (this is not the working example, it's just to show the idea of what I want to accomplish):
const schemas = {
'/users': 'some validation schema',
'/users/:id': 'another validation'
}
module.exports = (req, res, next) => {
const url = req.originalUrl; // This is where I'm stuck.
if (!schemas[url]) {
// throw new error that validation failed
}
// validating somehow
if (!req.validate(schemas[url])) {
// throw new error that validation failed
}
return next();
}
And for this, I need to get the middlelware mount folder (like '/users/:id' for '/users/557'). I've tried to use req.originalUrl, but it returns the full URL path instead of the mount folder.
How can I achieve this? And if there's no way, how can I write my validation middleware another way to make it work?
Inside req.route you will get the path of API.
Check this screenshot

Mongoose and multiple database in single node.js project

I'm doing a Node.js project that contains sub projects. One sub project will have one Mongodb database and Mongoose will be use for wrapping and querying db. But the problem is
Mongoose doesn't allow to use multiple databases in single mongoose instance as the models are build on one connection.
To use multiple mongoose instances, Node.js doesn't allow multiple module instances as it has caching system in require(). I know disable module caching in Node.js but I think it is not the good solution as it is only need for mongoose.
I've tried to use createConnection() and openSet() in mongoose, but it was not the solution.
I've tried to deep copy the mongoose instance (http://blog.imaginea.com/deep-copy-in-javascript/) to pass new mongoose instances to the sub project, but it throwing RangeError: Maximum call stack size exceeded.
I want to know is there anyways to use multiple database with mongoose or any workaround for this problem? Because I think mongoose is quite easy and fast. Or any other modules as recommendations?
According to the fine manual, createConnection() can be used to connect to multiple databases.
However, you need to create separate models for each connection/database:
var conn = mongoose.createConnection('mongodb://localhost/testA');
var conn2 = mongoose.createConnection('mongodb://localhost/testB');
// stored in 'testA' database
var ModelA = conn.model('Model', new mongoose.Schema({
title : { type : String, default : 'model in testA database' }
}));
// stored in 'testB' database
var ModelB = conn2.model('Model', new mongoose.Schema({
title : { type : String, default : 'model in testB database' }
}));
I'm pretty sure that you can share the schema between them, but you have to check to make sure.
Pretty late but this might help someone. The current answers assumes you are using the same file for your connections and models.
In real life, there is a high chance that you are splitting your models into different files. You can use something like this in your main file:
mongoose.connect('mongodb://localhost/default');
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () => {
console.log('connected');
});
which is just how it is described in the docs. And then in your model files, do something like the following:
import mongoose, { Schema } from 'mongoose';
const userInfoSchema = new Schema({
createdAt: {
type: Date,
required: true,
default: new Date(),
},
// ...other fields
});
const myDB = mongoose.connection.useDb('myDB');
const UserInfo = myDB.model('userInfo', userInfoSchema);
export default UserInfo;
Where myDB is your database name.
One thing you can do is, you might have subfolders for each projects. So, install mongoose in that subfolders and require() mongoose from own folders in each sub applications. Not from the project root or from global. So one sub project, one mongoose installation and one mongoose instance.
-app_root/
--foo_app/
---db_access.js
---foo_db_connect.js
---node_modules/
----mongoose/
--bar_app/
---db_access.js
---bar_db_connect.js
---node_modules/
----mongoose/
In foo_db_connect.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/foo_db');
module.exports = exports = mongoose;
In bar_db_connect.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/bar_db');
module.exports = exports = mongoose;
In db_access.js files
var mongoose = require("./foo_db_connect.js"); // bar_db_connect.js for bar app
Now, you can access multiple databases with mongoose.
As an alternative approach, Mongoose does export a constructor for a new instance on the default instance. So something like this is possible.
var Mongoose = require('mongoose').Mongoose;
var instance1 = new Mongoose();
instance1.connect('foo');
var instance2 = new Mongoose();
instance2.connect('bar');
This is very useful when working with separate data sources, and also when you want to have a separate database context for each user or request. You will need to be careful, as it is possible to create a LOT of connections when doing this. Make sure to call disconnect() when instances are not needed, and also to limit the pool size created by each instance.
Mongoose and multiple database in single node.js project
use useDb to solve this issue
example
//product databse
const myDB = mongoose.connection.useDb('product');
module.exports = myDB.model("Snack", snackSchema);
//user databse
const myDB = mongoose.connection.useDb('user');
module.exports = myDB.model("User", userSchema);
A bit optimized(for me atleast) solution. write this to a file db.js and require this to wherever required and call it with a function call and you are good to go.
const MongoClient = require('mongodb').MongoClient;
async function getConnections(url,db){
return new Promise((resolve,reject)=>{
MongoClient.connect(url, { useUnifiedTopology: true },function(err, client) {
if(err) { console.error(err)
resolve(false);
}
else{
resolve(client.db(db));
}
})
});
}
module.exports = async function(){
let dbs = [];
dbs['db1'] = await getConnections('mongodb://localhost:27017/','db1');
dbs['db2'] = await getConnections('mongodb://localhost:27017/','db2');
return dbs;
};
I have been using this method and it works great for me until now.
const mongoose = require('mongoose');
function makeNewConnection(uri) {
const db = mongoose.createConnection(uri, {
useNewUrlParser: true,
useUnifiedTopology: true
});
db.on('error', function (error) {
console.log(`MongoDB :: connection ${this.name} ${JSON.stringify(error)}`);
db.close().catch(() => console.log(`MongoDB :: failed to close connection ${this.name}`));
});
db.on('connected', function () {
mongoose.set('debug', function (col, method, query, doc) {
console.log(`MongoDB :: ${this.conn.name} ${col}.${method}(${JSON.stringify(query)},${JSON.stringify(doc)})`);
});
console.log(`MongoDB :: connected ${this.name}`);
});
db.on('disconnected', function () {
console.log(`MongoDB :: disconnected ${this.name}`);
});
return db;
}
// Use
const db1 = makeNewConnection(MONGO_URI_DB1);
const db2 = makeNewConnection(MONGO_URI_DB2);
module.exports = {
db1,
db2
}

Categories