Auto increment sequence in Mongoose - node.js

I am trying to implement Auto increment in uisng mongoose.
But I am stuck.
Counter Schema
counter.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var counterSchema = new Schema({
_id: {type: String, required: true},
sequence_value: {type: Number, default: 1}
});
var Counter = module.exports = mongoose.model('Counter', counterSchema);
Product Schema
products.js
var productsSchema = new Schema({
productId: {type: String, require: false},
merchantId: {type: String, required: false}
)}
I have created counter collection and inserted one record inside it.
{
"_id" : "productId",
"sequence_value" : 1
}
Include method to increment the counter in the counter collection
//COUNTER COLLECTION
function getNextSequenceValue(sequenceName){
var sequenceDocument = Counters.findOneAndUpdate({
query:{_id: sequenceName },
update: {$inc:{sequence_value:1}},
new:true
});
return sequenceDocument.sequence_value;
}
Calling method to increment sequence number:
product.productId = getNextSequenceValue("productid");
But it's not working, nothing is getting saved in the products collection?

the next sequence should be
product.productId = getNextSequenceValue("productId"); // camelCase
in the counter collection you have added document with key productId (camelCase) but trying to get sequence with key productid (all lowercase)
mongo CLI
> function getNextSequenceValue(sequenceName){
...
... var sequenceDocument = db.counters.findOneAndUpdate(
... { "_id" : sequenceName },
... { $inc : { sequence_value : 1 } },
... { new : true }
... );
... return sequenceDocument.sequence_value;
... }
>
EDIT-2 with mongoose
var counterSchema = mongoose.Schema(
{
_id: { type: String, required: true },
sequence_value: { type: Number, default: 1 }
}
);
var Counters = mongoose.model('Counters', counterSchema);
var productsSchema = mongoose.Schema({
productId: {type: String, require: true},
merchantId: {type: String, required: false}
});
productsSchema.pre('save', function(next){
var doc = this;
Counters.findOneAndUpdate(
{ _id: 'productId' },
{ $inc : { sequence_value : 1 } },
{ new : true },
function(err, seq){
if(err) return next(err);
doc.productId = seq.sequence_value;
next();
}
);
}
);
var Product = mongoose.model('Product', productsSchema);
var testProduct = new Product({merchantId : 'test'})
testProduct.save(function (err, doc){
console.log('saved ' + doc )
})
output (with generated productId)
saravana#ubuntu:~/node-mongoose$ node app.js
`open()` is deprecated in mongoose >= 4.11.0, use `openUri()` instead, or set the `useMongoClient` option if using `connect()` or `createConnection()`. See http://mongoosejs.com/docs/connections.html#use-mongo-client
Mongoose: counters.findAndModify({ _id: 'productId' }, [], { '$inc': { sequence_value: 1 } }, { new: true, upsert: false, remove: false, fields: {} })
Mongoose: products.insert({ productId: '36', merchantId: 'test', _id: ObjectId("5a5b27b860716d24007df611"), __v: 0 })
saved { __v: 0,
productId: '36',
merchantId: 'test',
_id: 5a5b27b860716d24007df611 }
^C
saravana#ubuntu:~/node-mongoose$

Related

How to use mongoose to make changes in two different collections in one nodejs query

In this application, I am trying to update a field value, if it is successful then I want to save into a log collection, however, not all the data are saved in the log collection, I am not sure if I am doing it the right way, would appreciate if someone could help out.
here is the query :
// both models(Log & Inventory are imported)
router.get("/add_product/:id/:num/:quantity/:order", (req, res) => {
var id = req.params.id;
var quantity = req.params.quantity;
var order = req.params.order;
// console.log('id----', id);
var num_mod = req.params.num;
var modified_count = parseInt(num_mod) - parseInt(quantity);
console.log("num_mod----", num_mod);
Inventory.findByIdAndUpdate(id, { quantity: parseInt(num_mod) }, { new: true }, function(
err,
inventory
) {
if (err) {
console.log("err", err);
res.status(500).send(err);
} else {
console.log(inventory.name);
const newLog = new Log({
name: inventory.name,
description: inventory.description,
price: parseInt(inventory.price),
quantity: parseInt(inventory.quantity),
modified_quantity: parseInt(modified_count),
itemDest: order //this is not being saved
});
newLog.save(function(err, Log) {
if (err) {
console.log(err);
} else {
console.log("add log success");
res.send(inventory);
}
});
}
});
});
URL from front end :
// order is a string
here is the Log schema :
const mongoose = require("mongoose");
const LogSchema = new mongoose.Schema(
{
// _id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true },
description: { type: String, required: true },
price: { type: Number, required: true },
quantity: { type: Number, required: true },
modified_quantity: { type: Number, required: true },
supplier: String,
taxable: Boolean,
itemDest: String
},
{ timestamps: true }
);
// Create model from the schema
const Log = mongoose.model("Log", LogSchema);
// Export model
module.exports = Log;
and here is the inventory schema
const mongoose = require("mongoose");
//create Schema
const InventorySchema = new mongoose.Schema(
{
// _id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true },
description: { type: String, required: true },
price: { type: Number, required: true },
quantity: { type: Number, required: true },
supplier: String,
taxable: Boolean
},
{ timestamps: true }
);
// Create model from the schema
const Inventory = mongoose.model("Inventory", InventorySchema);
// Export model
module.exports = Inventory;
My issue is with this line "itemDest: order" in the query, I intend to save the value of "order" extracted from "req.params.order" into "itemDest" but it doesn't save.

Mongoose populate returning data without population

I know that this question was asked many many times but i still can't find a solution
So this is my db
Product :
Ingredient :
Schemas :
ingredient.js
const mongoose = require("mongoose");
var IngredientSchema = new mongoose.Schema({
quantity: {
value: Number,
unit: String
},
comment: String,
product: { type: mongoose.Schema.Types.ObjectId, ref: "Product" }
});
module.exports = mongoose.model("IngredientSchema", IngredientSchema);
product.js
const mongoose = require("mongoose");
var ProductSchema = new mongoose.Schema({
name: {
type: String,
default: "",
trim: true,
required: "Name cannot be blank"
},
category: {
type: String,
default: "",
trim: true
},
convertion: [
{
unit_from: String,
unit_to: String,
value_from: Number,
value_to: Number
}
],
default_unit: String
});
const Product = (module.exports = mongoose.model(
"ProductSchema",
ProductSchema
));
this is the populate function :
ingredientRoutes.route("/:id").get(function(req, res) {
let id = req.params.id;
Ingredient.findById(id)
.populate("produit")
.exec()
.then(function(data) {
console.log(data.product, "***");
})
.catch(function(err) {
console.log(err);
});
});
this is the result that i'm getting :
just the id of the product without making the population
Any idea ?

Cast to ObjectId failed for value "" at path "_id" for model

I have already checked the other entries on StackOverflow, but it did not help.
I am building a RESTapi with node.js, and I am using MongoDB with mongoose
I have a Schema that contains three different models. I am able to save POST request to the entry. I am sure that entry is saved because I checked on atlas.mongo. However, I have a problem when I am trying to use GET request.
It gives this error:
Cast to ObjectId failed for value "" at path "_id" for model
These are my Models: (These models are in different files)
const Model1 = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
word1: { type: [String], require: true }
});
----------------------------------------------
const Model2 = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
word2: { type: [String], require: true }
});
----------------------------------------------
const Model3 = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
element1: { type: [String], default: ""},
element2: { type: [String], default: ""}
});
----------------------------------------------
const Word = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
md3: { type: mongoose.Schema.Types.Mixed, ref: 'Model3', require: true },
md2: { type: mongoose.Schema.Types.Mixed, ref: 'Model2', require: true },
md1: { type: mongoose.Schema.Types.Mixed, ref: 'Model1', require: true }
});
This is my POST request:
exports.entry_create = (req, res, next) => {
const newModel3 = new Model3({
_id: new mongoose.Types.ObjectId(),
element1: req.body.element1,
element2: req.body.element2
});
const newModel2 = new Model2({
_id: new mongoose.Types.ObjectId(),
word2: req.body.word2
});
const newModel1 = new Model1({
_id: new mongoose.Types.ObjectId(),
word1: req.body.word1
});
const newEntry = new Word({
_id: new mongoose.Types.ObjectId(),
md3: newModel3,
md2: newModel2,
md1: newModel1
});
newEntry
.save(); // i have also then() and catch() part
};
This is where I got the error on Postman
exports.entry_get_all = (req, res, next) => {
Word.find()
.select('_id md3 md2 md1')
.populate('md3')
.populate('md2')
.populate('md1')
.exec()
.then(docs => {
res.status(200).json({
numOfEntries: docs.length,
Entries: docs.map(doc => {
return {
_id: doc._id,
md3: doc.md3,
md2: doc.md2,
md1: doc.md1,
request: { type: 'GET' }
}
})
});
}); // i have also catch() part
};
What could be the problem? Is _id's of md3, md2 & md1 returns null?
I believe it has to do with your references md1, md2 and md3. The way you reference another model is by the _id, which in your case it's and ObjectId. That being said, when you define md1, md2, and md3 you say the type is mixed, not an ObjectId. Do this instead:
const Word = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
md3: { type: mongoose.Schema.Types.ObjectId, ref: 'Model3', require: true },
md2: { type: mongoose.Schema.Types.ObjectId, ref: 'Model2', require: true },
md1: { type: mongoose.Schema.Types.ObjectId, ref: 'Model1', require: true }
});
Also note: You don't need to explicitly create a new ObjectId when creating an instance of your model. If using mongoose, it creates the _id for you! So you can just create a new Word like this:
let md1 = null;
let md2 = null;
let md3 = null;
const newModel3 = new Model3({
element1: req.body.element1,
element2: req.body.element2
});
// Save newModel3
newModel3.save()
.then((_md3) => {
md3 = _md3;
const newModel2 = new Model2({
word2: req.body.word2
});
return newModel2.save();
})
.then((_md2) => {
md2 = _md2;
const newModel1 = new Model1({
word1: req.body.word1
});
return newModel1.save();
})
.then((_md1) => {
md1 = _md1
const newEntry = new Word({
md3: md3._id,
md2: md2._id,
md1: md1._id
});
return newEntry.save();
})

How to get particular documents of a schema which does not have empty array of referenced schema

My code is as shown below:
foodtruck.js
var FoodTruckSchema = new Schema({
foodtruck_name:String,
item_list: [ {type : mongoose.Schema.ObjectId, ref : 'items'}]
},{ versionKey: false });
items.js
var ItemSchema = new Schema({
item_name: String,
item_description: String,
item_illustrations: [String],
item_stock: {
type: Number,
default: 0
} ,
no_of_likes: {
type: Number,
default: 0
}
}, {
versionKey: false
});
My query is as shown below:
const searchItems = (req, res) => {
let item_name = req.query.item_name;
foodtr.find().populate({
path: 'item_list',
match: {
item_name: item_name,
item_stock: { $ne: 2 }
}
}).exec(function(err, foodtrucks) {
res.json({
status: '200',
message: 'searched items',
data: foodtrucks
});
});
};
What I want here is, I want only those foodtrucks in which queried item_name matches with referenced item_name , otherwise , I do not want to show that particular foodtruck. Right now, I am getting also those foodtruck in which item_list is empty array. How to alleviate this situation?

Getting error when upsert=true in mongoose

I am using mongoose for my mongodb.
I am trying to update the existing document with an array of data.
Here's my code:
exports.transactions = function(req,res)
{
var transactions = req.body.transactions;
transactions.forEach(function(transaction){
// console.log("hello "+transaction);
// });
console.log(req.body.user._id);
Dwolla.update({user_id: req.body.user._id}, {$push: {"transactions": {Amount: transaction.Amount, DestinationId: transaction.DestinationId, DestinationName: transaction.DestinationName, SourceId:transaction.SourceId,SourceName:transaction.SourceName,status:transaction.Status}}},
{ upsert: true},
function(err, model) {
if(err) console.log(err);
console.log("success");
}
);
});
}
The error i am getting when upsert is true is:
oldCb(error, result ? result.result : { ok: 0, n: 0, nModified: 0 });
TypeError: object is not a function
at Query.callback (E:\ndash-nodejs\node_modules\mongoose
)
at E:\ndash-nodejs\node_modules\kareem\index.js:177:19
at E:\ndash-nodejs\node_modules\kareem\index.js:109:16
at process._tickCallback (node.js:355:11)
Model:
'use strict';
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var dwollaSchema = new Schema({
user_id:{ type: String},
username: { type: String },
dwolla_id: { type: String },
transactions: [{
Amount: String,
DestinationId:String,
DestinationName:String,
SourceId:String,
SourceName:String,
status:String
}],
modified: { type: Date, default: Date.now }
});
module.exports = mongoose.model('Dwolla',dwollaSchema);

Resources