I've looked everywhere and I cannot figure out why I get this error while I try to create and save documents with Mongoose.
It has worked to save individual documents with await fruit.save();, but when I run the script to add multiple documents with .insertMany() I get the following message in terminal and I have no clue what to do with it.
/Users/FruitsProjectMongoose/node_modules/mongoose/lib/model.js:3519
for (let i = 0; i < error.writeErrors.length; ++i) {
^
TypeError: Cannot read properties of undefined (reading 'length')
at /Users/FruitsProjectMongoose/node_modules/mongoose/lib/model.js:3519:47
at collectionOperationCallback (/Users/FruitsProjectMongoose/node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js:194:24)
at /Users/FruitsProjectMongoose/node_modules/mongodb/lib/utils.js:349:66
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
It would be an understatement to say that I have tried everything that I could think of/find across the web. I’ve messaged a few devs. and they’ve recommended me to try some things but no luck. I really need some help with this. I start to think it might be something wrong with my system.
I’ve installed MongoDB through Homebrew and Mongoose through npm in the past two days so everything is up-to-date.
The fruitsDB exists and I am able to access and view the collections and the individually added documents through the MongoDB shell mongosh.
Here is my simple JS script:
const mongoose = require("mongoose");
mongoose.set('strictQuery', false);
// Connect to MongoDB by port and catch errors.
main().catch(err => console.log(err));
async function main() {
await mongoose.connect('mongodb://127.0.0.1:27017/fruitsDB')
.then(() => console.log('Connected!'));
// Defining a Model Schema.
const Schema = mongoose.Schema;
const fruitSchema = new Schema({
name: {
type: String,
require: true
},
rating: {
type: Number,
require: true
},
review: {
type: String,
require: true
}
});
const peopleSchema = new Schema({
name: String,
age: Number
});
// Create a Model.
const Fruit = new mongoose.model("Fruit", fruitSchema);
const People = new mongoose.model("People", peopleSchema);
// Create & Save a Document.
const fruit = new Fruit({
name: "Banana",
rating: 10,
review: "Perfection!"
});
// await fruit.save();
const people = new People({
name: "Eduard",
age: 25
});
// await people.save();
// Create & Save docs. in Bulk.
const kiwi = new Fruit({
name: "Kiwi",
rating: 9,
review: "Great, kinda expensive!"
});
const orange = new Fruit({
name: "Orange",
rating: 6,
review: "Too sweet."
});
const apple = new Fruit({
name: "Apple",
rating: 7,
review: "Great fruit!"
});
Fruit.insertMany([kiwi, orange, apple], function(err) {
if (err) {
console.log(err);
} else {
console.log("Succesfully saved to fruitsDB");
}
});
mongoose.connection.close();
};
MongoDB server is running on brew services start mongodb-community.
This error is likely caused by an issue with the Mongoose library. To fix it, try updating the Mongoose library to the latest version. You can do this by running the following command in your terminal:
npm install mongoose#latest --save
If the "error" object is not defined, make sure that it is properly initialized before attempting to access its properties.
I've missed a set of curly braces. So the correct syntax is this.
await Fruit.insertMany([kiwi, orange, apple], {function(err) {
if (err) {
console.log(err);
} else {
console.log("Succesfully saved to fruitsDB");
}
}});
Related
I have logged the dbSong and results are satisfying, but they are not being saved into database.
The schema and all is like this.
const baseURL = "https://songspk.mobi";
mongoose.connect("mongodb://localhost:27017/songsDB", {useNewUrlParser: true, useUnifiedTopology: true});
//New Song Schema
const songSchema = new mongoose.Schema({
name: String,
parent_url: String,
child_url: String,
album: String,
duration: String,
singers: String,
lyricist: String,
music_director: String,
download_128: String,
download_320: String,
image_url: String
});
const Song = mongoose.model("Song", songSchema);
This is distribution of work.
if(cluster.isMaster) {
console.log(`I'm Master ${process.pid}`);
for(let i=0;i<numCPUs;i++) { //Forking all 8 CPUs
cluster.fork();
}
} else {
const wokerID = cluster.worker.id;
fetchResults(links[wokerID-1]);
fetchResults(links[wokerID + 7]);
fetchResults(links[wokerID + 15]);
if(wokerID === 1) {
fetchResults(links[24]);
}
if(wokerID === 2) {
fetchResults(links[25]);
}
//console.log(`I'm worker ${process.pid}`);
process.exit();
}
I'm using cluster for higher performance. So, I have started calling functions on each CPU, and it's working. The work is now very fast, almost 8 times and it's logging what it is doing. Each CPU is working parallelly and calling a function names fetchResults(), which is fecthing some results from a website.
Now inside fetchResults() function, a link has been passed and it goes to a web page and fetches all the song details, let say 25 songs on a link.
function fetchResults(link) {
const result = makeGetRequest(link);
const dom = new jsdom.JSDOM(result);
const numberOfSongs = dom.window.document.querySelectorAll(".thumb-image a[href]").length;
for(var i=0;i<numberOfSongs;i++) { //Particular Song
const song = {
name: "",
parent_url: link,
child_url: "",
album: "",
duration: "",
singers: "",
lyricist: "",
music_director: "",
download_320: "",
download_128: "",
image_url: ""
};
// I have put all songs details in this song object. Now I want to save this into my
//database
const dbSong = new Song({
name: song.name,
parent_url: song.parent_url,
child_url: song.child_url,
album: song.album,
duration: song.duration,
singers: song.singers,
lyricist: song.lyricist,
music_director: song.music_director,
download_128: song.download_128,
download_320: song.download_320,
image_url: song.image_url
});
//console.log(dbSong);
dbSong.save(function(err){
if(err) {
console.log(err);
} else {
console.log("*********I did that********");
}
});
}
}
Now if I log dbSong or song it shows everything on console, but nothing error or Success message in console. And also, it is not saving any data into database. Please help me. If I save data outside the function it saves that correctly, but not inside the function which contains a loop. I'm not getting why it is so, may me something like sync or async, please help me!
When I tried to use
const promise = dbSong.save();
console.log(promise);
I got result on log as:
Promise { <pending> }
I know this question has been asked before but I feel like I'm doing everything right and I'm still having an issue. I want to save an item from a form into my mongodb collection using mongoose.
My schema:
// stationmodel.js
export const StationSchema = new mongoose.Schema({
"FDID": String,
"Fire dept name": String,
"HQ addr1": String,
"HQ city": String,
"HQ state": String,
"HQ zip": Number,
"HQ phone": String,
"Dept Type": String,
"Organization Type": String,
"Website": String,
"Number Of Stations": Number,
"Primary agency for emergency mgmt": Boolean,
}, {collection: "FEMA_stations"})
In my express app:
// in routes.js
const StationSchema = require('./stationmodel')
const Station = mongoose.model('Station', StationSchema, 'FEMA_stations')
const addstation = (req, res) => {
console.log(req.body)
const newStation = new Station(req.body)
newStation.save( function(err){
if (err) { console.error(err) }
console.log('newStation after save', newStation)
})
}
const routes = app => {
app.route('/api/addstation')
.post(addstation)
}
export default routes
// in index.js
import routes from './routes'
app.use(bodyParser.urlencoded({ extended: true }))
app.use(bodyParser.json())
routes(app)
In my front end code, calling to the backend in a redux action:
fetch('/api/addstation', {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(stationToAdd)
})
When I console.log(req.body) on my back end, I get the data I'm expecting. It looks something like this:
{
FDID: '202020',
'Fire dept name': 'Some Fire Department',
'HQ addr1': 'Some address',
'HQ city': 'San Dimas',
'HQ state': 'CA',
'HQ zip': 99999,
'HQ phone': '5555555555',
'Dept Type': 'Career',
'Organization Type': 'State',
Website: '',
'Number Of Stations': 0,
'Primary agency for emergency mgmt': true,
}
But when I console.log my newStation that I'm trying to .save(), all I get is a response like this:
{ _id: 5efe29911ea067248f3c39a0, __v: 0 }
I know other people had issues with their schema, their model, making sure that they're truly connected to their mongodb collection, or making sure that the request is made with the application/json header, but I feel I have all those things right. The code was pieced together from a much more modularized app to try to cut the fat and present the core issue, so let me know if I'm missing any glaring information.
What might be going wrong here? Why is the data from req.body not making it into my new document that I'm trying to save to the collection? Thanks for reading.
You are mixing es6 module import/export with Node.js CommonJS require.
In stationmodel.js You are using a "named export"
export const StationSchema = new mongoose.Schema(...
But in routes.js you are using CommonJS require
const StationSchema = require('./stationmodel')
Which is likely to be an empty object. So the following line will create a model with an "empty" schema
const Station = mongoose.model('Station', StationSchema, 'FEMA_stations')
The solution
use named import instead
import { StationSchema } from './stationmodel'
TIP:
Since you are already name the file stationmodel.js, which suggests it's a model. You can put the following in stationmodel.js directly to prevent the model from getting incorrect schema
export const Station = mongoose.model('Station', StationSchema, 'FEMA_stations')
I'm trying to find a specific row in the database based on the user's message, namely: catalystname.
Within the schema I have successfully indexed the given string as text:
const { Schema } = mongoose;
const scheduleMessageSchema = new Schema({
_id: { type: Schema.Types.Oid, auto: true },
catalystname: String,
catalystdesc: String,
catalystquest: String,
date: String,
});
scheduleMessageSchema.index({catalystname: 'text'});
module.exports = mongoose.model('dbcatalyst', scheduleMessageSchema);
My search code:
const Catal = require("../src/models/dbcatalyst.js")
module.exports.run = async (client, message, args) => {
message.content = args.slice(0).join(" ")
Catal.find({$text: {$search: message.content}})
.exec(function(docs){
let embedlogs3 = new Discord.RichEmbed()
.setAuthor(`1`, message.author.displayAvatarURL)
.setDescription(`${docs}`)
.setColor("#33ffff")
message.channel.send(embedlogs3)
/*/ ${collected.first().content}/*/
});
}
And started searching for the required line in the message. The bot successfully copes with its task, but displays the entire document in full instead of 1 line.
_id: 5e243704961eb23c106bfb02,
catalystname: 'Чёрный Коготь',
catalystdesc: '0',
catalystquest: '0',
date: '1579430157018',
__v: 0
}
Can I somehow output exactly the string? catalystname
Looking at the Mongoose documentation, it seems the callback takes two parameters:
err An error or null
docs The returned document(s)
Change your callback to
Catal.find({$text: {$search: message.content}})
.exec(function(err, docs){
...
});
and you should receive an array of matching documents.
I am a beginner in Backend developing, and I have this array called (Movie). I use expressJS and I want to save the array on MongoDB.I will use Mongodb atlas for my database. I appreciate your help
I tried to follow this instruction on this website:
https://medium.com/#lavitr01051977/node-express-js-aea19636a500
I ignored the first steps and starts from ( Connecting to the Database ) title but It doesn't work.
var express = require('express')
var app = express()
app.get('/', (req, res) => {
res.send('ok')
});
//movie array
const movies = [
{ title: 'Jaws', year: 1975, rating: 8 },
{ title: 'Avatar', year: 2009, rating: 7.8 },
{ title: 'Brazil', year: 1985, rating: 8 },
{ title: 'الإرهاب والكباب', year: 1992, rating: 6.2 }
]
//read the array movie
app.get('/movies/read/',(req,res) => {
res.send({status:200, data:movies})
})
//add elements to array movies
app.get('/movies/add',(req,res) => {
var t = req.query.title
var y = req.query.year
var r = req.query.rating
if(t == undefined || y == undefined || y.length > 4 || isNaN(y)) {
res.send({status:403, error:true, message:'you cannot create a movie without providing a title and a year'})
}
if (r == "") {
r = 4
}
movies.push({title: t, year: y, rating: r})
res.send({status:200, data:movies})
})
//delete elements from array movies
app.get('/movies/delete/:ID',(req,res) => {
var d = req.params.ID
if (d > 0 && d < movies.length ) {
movies.splice(d-1, 1)
res.send({status:200, message: movies})
}
else {
res.send({status:404, error:true, message:'the movie <ID> does not exist'})
}
})
//update elements from array movies
app.get('/movies/update/:ID',(req,res) => {
let c = req.params.ID
let x = req.query.title
let y = req.query.year
let z = req.query.rating
function update(a, b) {
if(a != undefined || a == "") {
movies[c-1][b] = a
}
}
if(c > 0 && c < movies.length ) {
update(x, 'title')
update(y, 'year')
update(z, 'rating')
res.send({status:200, message: movies})
}
else {
res.send({status:404, error:true, message:'the movie <ID> does not exist'})
}
})
app.listen(3000, () => console.log('listinig on port 3000'))
I expect the answer is like the link that I put it above on medium.com website
mongoose is a framework that facilitates interacting with MongoDB. Actually you basically never want to do all the validation, casting, and logic boilerplate on your own, so why reinvent the wheel.
And since you're a beginner, don't be afraid of frameworks. There are many useful frameworks for many areas of backend and frontend to make life easier for you.
The article you shared is self-explanatory, but I will sum up only the database part for you (I won't go deep into your code, no donkey work. the rest is up to you):
1) First of all install mongoose.
npm install mongoose
The article has --save which is no need to add anymore, as "npm install saves any specified packages into dependencies by default."(ref.)
2) to able to access and use mongoose, you need to import it, in node way, that is require().
const express = require(‘express’)
const mongoose = require(“mongoose”);
const bodyParser = require(‘body-parser’);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
And what's body-parser there for?
When dealing with database in express, you'll sooner or later come across errors like this one.
and the reason why we need one after all is best explained in this answer.
Also, recent versions of express has its own body parser now, so you can use app.use(express.json()) instead of app.use(bodyParser.json()).
Important: body-parser must be before your routes.
3) use mongoose.connect(url).
url argument is what you find in your MongoDB Atlas. :
Location: clusters tab -> connect -> connect your application -> driver node.js
Which gives you, something like this:
mongodb+srv://<user>:<password>#,cluster>.mongodb.net/test?retryWrites=true&w=majority
Important: you use user and password of the user you made within Database Access tab, not your own user and password.
You can set up your environment variables to secure sensitive and changeable data. But I prefer using config.js for simplicity, and which usually resides in the root of app.
Not only you can secure them (like for using .gitignore), but also easily modify them as there are variables that might change from one environment to another environment, making them available in one place and easy to find, instead of looking for them to change all over your app.
For .env file approach, read this article.
Important: in case you want to put your code in github or anywhere online, which one reason we use config.js, don't forget to add this file in .gitignore to avoid such sensitive data get leaked and exposed to others online.
in config.js you can do so:
exports.username = 'your user';
exports.pass = 'your pass';
exports.myCluster = 'your cluster's name';
Then import them so:
const { username, pass, myCluster } = require('./config'); <- the path might be different for you!
Tip: You can use back-tick (` `) to easily insert those variables for const url, through interpolation.
That is:
const url = `mongodb+srv://${username}:${password},${myCluster}.mongodb.net/test?retryWrites=true&w=majority`
Important: make sure to whitelist your IP from MongoDB side (atlas), otherwise you will get connection error.
Under security: Network Access -> IP Whitelist
You could use 0.0.0.0/0 to whitelist all IPs.
Also, when using VPN, your IP will change too.
4) last but not least, after connecting to database, you need to define your schema:
const moviesSchema = new mongoose.Schema({
title: String,
year: Number,
rating: Number
});
And
const Movies = mongoose.model(“Movies”, moviesSchema);
Tip: A common mistake many newbies make is that they forgot to use new:
new mongoose.Schema({...})
If you want to create your model in a separate file (which is the best practice), you will need to modify your const Movies so:
module.exports = mongoose.model(“Movies”, moviesSchema);
Don't forgot to add const mongoose = require('mongoose'); in that separate js model file.
And in wherever you use want to use this model, you import so:
const Movies= require('../models/movies'); (the path may different for your app)
The rest, my friend, is up to you. What you want to do with your database and how to use it.
Note to others: I put so much time and mind to this as I was writing this. Please, if you see something wrong, or think you can add something, feel free to edit and improve my answer.
I would suggest you to take look at mongoose framework to interact with a Mongo database using NodeJS.
However, in the code you've provided you're not interacting with any database. You would need to define a Schema and then you could save a new doc or do any other action with your collection. Please follow some 'Get started' guide on how to do it.
Hope it helps!
I ll explain step by step. NOTE THAT THIS PROCESS SHOULD BE RUN ONLY ONCE. SO YOU SHOULD ADD THIS CODE TO A SEPARATE MODULE AND RUN IT ONCE. otherwise you will keep adding more items to the db. lets name this module
movies.js
//you need to connect to mongodb through mongoose.
const mongoose = require("mongoose");
mongoose
.connect("mongodb://127.0.0.1:27017/movies", { //will create movies db automatically
useNewUrlParser: true,
useCreateIndex: true
})
.catch(err => {
console.log(err.message);
process.exit(1);
})
.then(() => {
console.log("connected");
});
//next create a schema and model:
const movieSchema = new mongoose.Schema({
title: String,
year: Number,
rating: Number
});
const Movie = mongoose.model("Movie", movieSchema);
//create movies array based on `Movie model` so u can use save() method.
const movies = [
new Movie({ title: "Jaws", year: 1975, rating: 8 }),
new Movie({ title: "Avatar", year: 2009, rating: 7.8 }),
new Movie({ title: "Brazil", year: 1985, rating: 8 }),
new Movie({ title: "الإرهاب والكباب", year: 1992, rating: 6.2 })
];
//Last step save it.
movies.map(async (p, index) => {
await p.save((err, result) => {
if (index === movies.length - 1) {
console.log("DONE!");
mongoose.disconnect();
}
});
});
map is an array method.it iterates over array and save each item inside the array. Once every item in the array is saved we need to disconnect from db. array method takes 2 arguments. on is each item inside the array, second one is the index of each item. index in array starts from 0, so last item's index in movies array is 3 but length of the array is 4 so once 4-1=3 that means we saved every item in the array.
Now run the code
node movies.js
I am trying to create a Schema with a 'price' field using Mongoose currency and follow the documentation on it. However the output does not show two decimals (499 instead of 4.99). If I use console.log to print the price, it shows the desired results, with two decimals. I wonder whether I misunderstood the Mongoose documentation on Currency or does the cause lie somewhere else.
This is my schema.
var mongoose = require('mongoose');
var assert = require('assert');
var Dishes = require('./models/stackmodel');
// Connection URL
var url = 'mongodb://localhost:27017/conFusion';mongoose.connect(url);
var db = mongoose.connection;
var product = new Dishes({ price: '4.99' });
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function () {
// we're connected!
console.log("Connected correctly to server");
// create a new dish
Dishes.create({
name: 'Uthapizza',
price: (product.price/100).toFixed(2),
}, function (err, dish) {
if (err) throw err;
console.log('Dish created!');
console.log(dish);
console.log(typeof (product.price/100).toFixed(2));
console.log((product.price/100).toFixed(2));
db.collection('dishes').drop(function () {
db.close();
});
});
});
This is my model.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
require('mongoose-currency').loadType(mongoose);
var Currency = mongoose.Types.Currency;
// create a schema
var dishSchema = new Schema({
name: {
type: String,
required: true,
unique: true
},
price: {
type: Currency,
require: true,
min: -20000,
max: 50000,
default: ''
}
});
var Dishes = mongoose.model('Dish', dishSchema);
// make this available to our Node applications
module.exports = Dishes;
And this is the print-out.
C:\ass2>node stack
Connected correctly to server
Dish created!
{ __v: 0,
name: 'Uthapizza',
_id: 58cd3dbd4319c51264489d8d,
price: 499 }
string
4.99
C:\ass2>
I have searched on the web, including on this site, but found no solution so far.
I use:
OS is Windows 7 32-bit
mongoose#4.8.6
node version v6.10.0
and while running npm list I got the following message (I suspect this might be the reason why I got the above problem):
npm ERR! extraneous: currency#3.0.0 C:\node_modules\currency
npm ERR! extraneous: mocha#3.2.0 C:\node_modules\mocha
npm ERR! extraneous: mongoose-currency#0.2.0 C:\node_modules\mongoose-currency
Thank's a lot beforehand.
Fairly late to the party but for future folks, this is how mongoose-currency stores float values. It first multiplies by 100 and then stores it. You should divide by 100 when retrieving values.
According to their readme on GitHub:
Saves a String as an integer (by stripping non-digits and multiplying by 100) to prevent rounding errors when performing calculations (See gotchas for details)
Example:
var product = new Product({ price: "$1,200.55" });
product.price; // Number: 120055
product.price = 1200;
product.price; // Number 1200 It will not round or multiply. Stored AS IS and should represent $12.00