Mongoose insertMany - Missing createdAt - javascript

I'm using mongoose in my Node micro service application.
I have a model with 'createdAt' that created automatically:
const mongoose = require('mongoose');
const recordSchema = new mongoose.Schema({
source: {
type: String,
required: true,
trim: true,
lowercase: true
},
coin: {
type: String,
required: true,
trim: true,
lowercase: true
},
rate: {
type: Number,
required: true
},
isError: {
type: Boolean,
required: true
},
}, { timestamps: { createdAt: 'created_at' } });
module.exports = mongoose.model('Record', recordSchema);
And I try to insert a bulk of documents into it, like this:
// Save the fetched data into the database.
const saveCoinsData = (coinsData) => {
RecordModel.collection.insertMany(coinsData, (err) => {
if (err) { logger.error(err); }
});
};
For some reason, if I insert a single document the 'createdAt' is created as expected. But if I use the insertMany function, it's not working and no 'createdAt' (or created_at) is created.
Is this normal?
Is this a bug in mongoose?

You're not using mongoose schema here. You're using default node drivers by using [schema].collection.[method]. Referring to this you can just use
RecordModel.insertMany instead, that should add the timestamps.

Instead of insertMany, maybe try create?
create triggers middleware save() which supports timestamps.
Reference:
Model.create
Unfortunately I cannot try this now, above is just based on Mongoose documentations

Related

Mongoose findByIdAndUpdate method not incrementing document value

I am trying to update the like count of job posts in my application using the $inc operator and the findByIdAndUpdate method from Mongoose. The correct document is being retrieved and returned but the like count for the job post never moves up from 0 and no updates are performed in the database collection.
Below is the code I am currently using to perform the update.
Jobs.findByIdAndUpdate(req.params._id , { $inc: {likes: 1}} , {new: true})
.then((ret) => {
res.send(ret)
})
Job schema
const mongoose = require('mongoose');
let JobSchema = mongoose.Schema({
student_name: {
type: String,
required: true
},
subject: {
type: String,
required: true
},
grade: {
type: Number,
required: true
},
area: {
type: String,
required: true
},
desc: {
type: String,
required: true
},
accepted: {
type: Boolean,
required: true,
default: false
},
tutor_name: {
type: String,
required: false
},
} , {collection: 'jobs'});
let Job = mongoose.model('Job' , JobSchema);
module.exports = Job;
Any insight into what is preventing the update from performing would be greatly appreciated
I have tried using two queries, one to retrieve the current likes of a post and another to manually update the doc with the incremented value. I have tried nesting the queries using .then() statements and have also tried the updateOne() and findOneAndUpdate() methods as alternatives. I have tried experimenting with the $set and $inc operators in my queries to see if either of them perform the changes, but neither do.
I am expecting the incremented 'likes' value to be reflected in the database and for the updated job document to be returned and echoed back to the console.
Your schema is missing a likes field, which means Mongoose will remove it from queries/updates (since it doesn't match the schema). Make sure to add it:
likes: {
type: Number,
default: 0
}
Can you try something like this (adding [] around update):
Jobs.findByIdAndUpdate(req.params._id , [{ $inc: {likes: 1}}] , {new: true})
.then((ret) => {
res.send(ret)
})
EDITED:
Jobs.findByIdAndUpdate(req.params._id , [{ $set: {likes: "$likes"+1}}] , {new: true})
.then((ret) => {
res.send(ret)
})

Add a new field to every document from my mongo DB collection via mongoose

This question was asked several times, but despite that, I wasn't able to solve my problem. In my mongoose collection, I store 30 users with the following mongoose schema. I want to implement a newsletter on my site, therefore I want to add the new field:
newsletter: {
type: Boolean,
default: true
},
My question is: How can I add newsletter false/true to every user?
I found that, but it didn't work.
User.updateMany({}, [{ $set: { newsletter: false }}])
My Schema:
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true },
password: { type: String, required: true },
date: { type: Date, default: Date.now },
token: { type: String, required: true }
});
const User = mongoose.model('User', UserSchema);
module.exports = User;
Adding to the schema "newsletter" does solve the problem for new users, but doesn't add the field to the already existing ones.

Node.js + Mongoose: How to use a virtual property to associate an ObjectID with the property?

I'm trying to access a MongoDB database using Node.js and Mongoose.
I created a virtual property in Schema called username. See the code that follows.
const mongoose = require("mongoose");
const User = require("../models/user");
const datatypes = ['temperature', 'humidity'];
const nodeSchema = new mongoose.Schema(
{
MACAddress: {
type: String,
required: true,
trim: true,
uppercase: true,
match: /^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$/,
},
alias: {
type: String,
trim: true,
},
coordinates: {
type: String,
required: false,
match: /^(\-?\d+(\.\d+)?),\s*(\-?\d+(\.\d+)?)$/,
},
address: {
type: String,
required: false,
},
userID: {
type: mongoose.Types.ObjectId,
},
nodeType: {
type: String,
enum: ['router', 'node'],
default: 'node',
},
dataTypes: {
type: [String],
enum: datatypes,
required: true,
}
},
{
timestamps: true,
}
);
The virtual property is used to set the userID property. See the code that follows.
// virtual field
nodeSchema.virtual("username").set(async function (username) {
this.userID = await this.getUserID(username);
});
// methods
nodeSchema.methods = {
getUserID: function (username) {
if (!username) return null;
return User.find({username: username}).then(userDoc => userDoc[0]._id);
},
};
To add a new document to the database, I am using the following code.
const newNode = new Node(newNodeData);
newNode.save().then( (node) => {
console.log(node.userID)
}
)
The problem is this... Calling the User.find function returns a promise. Even using await (see previous code), newNode.save() saves the document in the database without the userID property.
If I change the code to the following snippet, which doesn't use promise, the userID property is saved in the database with no problem. However, this is not what I want.
// virtual field
nodeSchema.virtual("username").set(async function (username) {
let ObjectId = mongoose.Types.ObjectId;
this.userID = new ObjectId("6245e896afe465a25047302e");
});
How can I force newNode.save() to wait for the promise result before saving the document to the database?

Mongoose autopopulate on create

I'm using the mongoose plugin autopopulate to populate docs from a separate collection. Here's a dumbed down schema:
const PostSchema = new Schema(
{
user: {
type: Schema.Types.ObjectId,
ref: 'user',
required: true,
autopopulate: {
select: ['firstName', 'lastName', 'email', 'username']
}
},
comment: { type: String }
}
)
Now, when I create a post with
const post = await Post.create({ user, comment });
It returns null for the populated user even though it shows up in the database and subsequent queries. I've used the { new: true } option on findByIdAndUpdate but it doesn't seem to work on create. Any thoughts on how to get create to return the populated docs?

MongoDB w/ Mongoose - Where to put syntax to ensureIndex spanning multiple fields?

I'm trying to implement this solution and I'm not sure where to put it. I see the db variable called frequently, but I'm still new to node and mongoDb, so I don't know how to call it in my Model. Here is the syntax to ensure an index spanning multiple fields...
db.collection.ensureIndex( {
description: "text",
title: "text"
} );
Here is my model...
// Module dependencies.
var mongoose = require('mongoose'),
config = require('../../config/config'),
Schema = mongoose.Schema,
findOrCreate = require('mongoose-findorcreate'),
textSearch = require('mongoose-text-search');
// Product Schema
var ProductSchema = new Schema({
created: {
type: Date,
default: Date.now
},
retailer: {
type: String,
required: true,
trim: true
},
retailer_category: {
type: String,
required: true,
trim: true
},
product_id: {
type: String,
required: true,
trim: true
},
link: {
type: String,
trim: true
},
title: {
type: String,
trim: true
},
price: {
type: Number
},
// Rating - 0 out of 5 (can be decimal)
rating: {
type: Number
},
description: {
type: String,
trim: true
},
variations: {
type: Schema.Types.Mixed,
default: []
},
images: {
type: Boolean,
default: false
}
});
// Validations
ProductSchema.index({ retailer: 1, product_id: 1 }, { unique: true });
// Statics
ProductSchema.statics = {
load: function(id, cb) {
this.findOne({
_id: id
}).exec(cb);
}
};
// Plug-Ins
ProductSchema.plugin(findOrCreate);
ProductSchema.plugin(textSearch);
mongoose.model('Product', ProductSchema);
var Product = mongoose.model('Product', ProductSchema);
Product.ensureIndexes( function(err) {
if (err) {
console.log(err);
}
})
It's worth noting:
When your application starts up, Mongoose automatically calls ensureIndex for each defined index in your schema. While nice for development, it is recommended this behavior be disabled in production since index creation can cause a significant performance impact. Disable the behavior by setting the autoIndex option of your schema to false.
from http://mongoosejs.com/docs/guide.html
I scratched my head over this one too. After digging around the mongoose test cases, I found that ensureIndex resides in a mongoose model's collection property.
var ProductModel = mongoose.model('Product', ProductSchema);
ProductModel.collection.ensureIndex({
description : 'text',
title : 'text'
}, function(error, res) {
if(error){
return console.error('failed ensureIndex with error', error);
}
console.log('ensureIndex succeeded with response', res);
});
Note that a callback is required, or Mongo will throw the error:
Error: Cannot use a writeConcern without a provided callback

Categories

Resources