I have a table and a form that retrieves datas and sends them to a database. After submitting the form, a new table rows is created with the datas just submitted.
I'd like to add a field for each rows with the date and time of the submit.
If I click on submit button, I do a http post request.
Is it possible to save the time and date of the submit?
I'm using mongoose for the db and express for the router.
import Router from 'express';
const router = Router();
router.post('/', isAuthorized(), async (req, res) => {
try {
let fruit = new Fruits(req.body);
await fruit.save();
res.json(fruit);
} catch (err) { res.status(503).send(err); }
});
You can set the timestamps of the POST request on the server-side, with your mongoose models.
In your mongoose Fruits Schema, you can add a timestamps field, with the default set to new Date(). So something like this:
const mongoose = require("mongoose");
const FruitSchema = new mongoose.Schema({
... other Fruit properties...
timestamps: { type: Date, default: () => new Date() }
});
Or instead, you can utilize mongoose's built in timestamps, by passing in a second object to your Schema, like this:
const mongoose = require("mongoose");
const FruitSchema = new mongoose.Schema({
... Fruit properties ...
}, {
timestamps: true
});
This will automatically add createdAt and updatedAt to your newly created Fruits documents.
You can get date and time using the Date object.
pass the below code into the code wherever you want to save. (like MongoDB)
let date_ob = new Date();
Read more about Date
Related
Using MERN-stack to build an app (MongoDB, ExpressJS, ReactJS, NodeJS)
I know there are plenty of docs/other solutions on stackoverflow for similar issues.
However, what confuses me about my scenario is that I'm not creating a new Date() object and then rendering it.
I have a backend model set up that has an attribute for Date, using Mongoose:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserSchema = new Schema({
username: {
type: String,
required: true,
unique: true
},
date: {
type: Date,
default: Date.now
}
})
module.exports = User = mongoose.model('user', UserSchema)
Now I'm simply rendering the user's data on a component/page but it comes out as
2020-05-10T17:57:14.987Z
You can use the moment library like so:
Documentation here
const myTime = moment(dateFromDB).format('hh:mm:ss') // or any other format
I have this schema in mongoose.
I want to delete a author that will deletes all author's stories.
is best way to do that in middleware express or middleware mongoose?
thanks
const authorSchema = new Schema ({
name : String,
stories : [{ type : ObjectId, ref:'Story'}]
})
const storySchema = new Schema({
title : String
})
Since it involves directly interacting with Mongoose and MongoDB, I'd suggest doing it in Mongoose middleware. Here's how you'd remove all the stories from a certain Author object:
let myAuthor = new Author(/* all the props */);
myAuthor.stories = [];
You can use Mongoose 'remove' middleware.
For example:
authorSchema.pre('remove', (next) => {
storySchema.remove({authorSchema_id: this._id}).exec();
next();
});
And documentation.
I was wondering if there's a way to insert documents into a MongoDB collection directly from a React component.
My current personal project (for training purpose) is a little chat web application. So for example, when my user wants to post a new message in a room, the input component should look something like this:
var NewMessageInput = React.createClass({
postMessage: function(value) {
db.collection.insert({
content: value
});
},
render: function() {
return (
<div>
<input onSubmit={() => this.postMessage(value)}>Type your message here</input>
</div>
);
}
});
I know how to get an app running with Express, React, and MongoDB but I'm only able to insert document with the mongo shell and querying them at the route loading. Plus, I would like to use only react-router for my routes and that's why I have this question.
I'm guessing you'll need the database on the server, so you may need an API to post the data since the database itself isn't on the client.
I use Superagent for sending the data and Mongoose to create a schema and mongo database.
messageModel.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// create a schema
const messageSchema = new Schema({
// You may need to add other fields like owner
addedOn: String,
message: String,
});
const Message = mongoose.model('Message', messageSchema);
module.exports = Message;
server.js
import Message from './models/messageModel';
mongoose.connect('mongodb://user:pass#localhost:port/database');
app.post('/api/messages', (req, res) => {
const doc = new Message({ message: req.body.message })
doc.save();
});
client.js
import React, { Component } from 'react';
import request from 'superagent';
class componentName extends Component {
constructor(props) {
super(props);
this.state = {
message: '',
};
this.handleMessageInput = this.handleMessageInput.bind(this);
}
handleMessageInput(e) {
this.setState({ message: e.target.value });
}
handleSubmitMessage() {
console.log('starting to submit profile');
if (this.state.isFormFilledProfile) {
console.log('Profile Form appears filled');
const data = {
message: this.state.message,
};
request
.post('/api/messages')
.send(data)
.set('Accept', 'application/json')
.end((err, res) => {
if (err || !res.ok) {
console.log('Oh no! err');
} else {
console.log('Success');
}
});
}
}
render() {
return (
<div>
<div>
<form onSubmit={this.handleSubmitMessage}>
<input
onChange={this.handleMessageInput}
value={this.state.message}
/>
<button type='Submit' value='Submit'>Submit</button>
</form>
</div>
</div>
);
}
}
export default componentName;
You may need to also go through the react forms guide here.
All the best!!!
Ok so because React is a front end framework you will not have access to things on your backend such as methods like db.collection.insert(). You will in tern has a separation of front end code and back end code. They will talk to each other through HTTP requests (GET, POST, PUT, DELETE).
Side note just to clarify. You will still need express for routing as well as react-router. They do different types of "routing". Express will handle routing of mainly your API, all the data calls that your front end will make to it. React-router handles page changes on your front end, right within the bowser. This keeps your page from reloading each time the user moves around.
So lets get into a little code.
On your back end you will need an express endpoint for your app to talk to. In this example I will show use with the package mongoose as it is a tool that is commonly used with a node.js backend.
https://www.npmjs.com/package/mongoose
var mongoose = require('mongoose');
var Message = require('../models/message');
app.post('/message', (req, res) => {
var newMessage = new Message(req.body);
newMessage.save((err, doc) => {
if (err) {
res.send(err);
} else {
res.send(doc);
}
});
});
This code will handle a post request at the url "/message". It will proceed to create a new message from the data in the request (req) body. Then save that to the database. After the save is successful it will send back the document that was just saved.
In mongoose we create a schema for each of our data models like such:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var MessageSchema = new Schema({
content: {
type: String,
},
createdAt: {
type: Date,
default: Date.now
}
});
var Message = mongoose.model('Message', MessageSchema);
module.exports = Message;
Now on the front end / React side of things we need to send our message data to the backend to save. We can use a package like axios to make clean promise based HTTP requests from the browser.
https://www.npmjs.com/package/axios
var NewMessageInput = React.createClass({
postMessage: function(value) {
axios.post('/message', {
content: value
})
.then(function (message) {
console.log(message);
})
},
render: function() {
return (
<div>
<input onSubmit={() => this.postMessage(value)}>Type your message here</input>
</div>
);
}
});
And that should do it!
For a backend example check out this repo I have setup. It's very basic but will be a good example of a backend with mongoose for reference.
https://github.com/Alexg2195/simple-dev-example
Also here is a bit of some side content I created for teaching React that may be a good reference.
https://github.com/Alexg2195/UT-ReactJS
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')
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
}