NodeJs Mongoose - remove one id from array in document - javascript

I have an array in my model document. I would like to remove one id in that array. Is this possible?
This is what I tried.
module.exports.RemoveFavourite = async (req, res, next) => {
try {
const userId = req.params.user;
const favouriteId = req.params.event;
const removeFavourite = await User.updateOne(
{ _id: userId },
{ $pull: { favourites: favouriteId } }
);
res.status(200).json(removeFavourite);
} catch {
res.status('404').json('error');
}
};

convert favouriteId string to ObjectId
const mongoose = require("mongoose")
module.exports.RemoveFavourite = async (req, res, next) => {
try {
const userId = req.params.user;
const favouriteId = req.params.event;
const removeFavourite = await User.updateOne(
{ _id: userId },
{ $pull: { favourites: mongoose.Type.ObjectId(favouriteId) } }
);
res.status(200).json(removeFavourite);
} catch {
res.status('404').json('error');
}
};

Related

Why could the findOrCreate plugin create several documents at once?

I'm currently working on a MERN application with following/follower function for the users. I decided to create separate schemas for following and follower relationships detached from user schema.
Follower schema
const mongoose = require('mongoose');
const findOrCreate = require('mongoose-findorcreate');
const ObjectId = mongoose.Schema.Types.ObjectId;
const followerSchema = mongoose.Schema({
userId: {
type: ObjectId,
ref: 'User'
},
follower: {
type: [ObjectId],
ref: 'User'
}
});
followerSchema.plugin(findOrCreate);
const Follower = mongoose.model('Follower', followerSchema);
module.exports = { followerSchema, Follower };
Following schema
const mongoose = require('mongoose');
const findOrCreate = require('mongoose-findorcreate');
const ObjectId = mongoose.Schema.Types.ObjectId;
const followingSchema = mongoose.Schema({
userId: {
type: ObjectId,
ref: 'User'
},
following: {
type: [ObjectId],
ref: 'User'
}
});
followingSchema.plugin(findOrCreate);
const Following = mongoose.model('Following', followingSchema);
module.exports = { followingSchema, Following };
The problem however starts in my service where followings are created as supposed to. However, for followers mongoose create 6-8 documents at once with userIds that don't even exist in my db.
Here's the code of the followerService (it's the first function)
const { Follower } = require('../models/followerModel');
const { Following } = require('../models/followingModel');
const { User } = require('../models/userModel');
const mongoose = require('mongoose');
exports.changeFollowStatus = async (user, userId) => {
console.log({ userId: userId, user: user._id });
const newFollowing = await Following.findOrCreate({ userId: user._id }, (err, following, created) => {
console.log({following: following});
if (!err && !isFollowing(following, userId)) {
following.following.push(mongoose.Types.ObjectId(userId));
following.save();
User.findByIdAndUpdate(mongoose.Types.ObjectId(userId), {$inc: {follower: 1}});
} else {
const followingIndex = following.following.indexOf(mongoose.Types.ObjectId(userId));
following.following.splice(followingIndex, 1);
following.save();
User.findByIdAndUpdate(mongoose.Types.ObjectId(userId), { $inc: { follower: -1 } });
}
});
const newFollower = await Follower.findOrCreate({ userId: mongoose.Types.ObjectId(userId) }, (err, follower, created) => {
console.log({follower: follower});
if (!err && !isFollower(follower, user._id)) {
follower.follower.push(user._id);
follower.save();
User.findByIdAndUpdate(user._id, { $inc: { following: 1 } });
} else {
const followerIndex = follower.follower.indexOf(user._id);
follower.follower.splice(followerIndex, 1);
follower.save();
User.findByIdAndUpdate(user._id, { $inc: { following: -1 } });
}
});
};
exports.showFollowings = async (userId) => {
const followings = await Following.findOrCreate({ userId: mongoose.Types.ObjectId(userId) });
return followings.following;
};
exports.showFollowers = async (userId) => {
const followers = await Follower.findOrCreate({ userId: mongoose.Types.ObjectId(userId) });
return followers.follower;
};
const isFollowing = (newFollowing, userId) => {
return newFollowing.following.includes(mongoose.Types.ObjectId(userId));
};
const isFollower = (newFollower, userId) => {
return newFollower.follower.includes(userId);
}
Now, my following adding code and follower adding code look almost identical, but for some reason for followers, mongoose creates many more documents. The strange thing is that there is a follower document with the correct userId, but many other with random userIds get created which doesn't happen with followings which works as supposed to.
I also checked whether I pass the correct values and everything seems to be fine. But just for reference, here's the controller function from which I pass the values.
exports.changeFollowingStatus = async (req, res, next) => {
passport.authenticate('jwt', async (err, user, info) => {
if (err) {
console.error({ authError: err });
};
if (info !== undefined) {
console.error({ authError: info.message });
res.status(403).send(info.message);
} else {
console.log({params: req.params});
const userToFollow = req.params.id;
await FollowerService.changeFollowStatus(user, userToFollow);
res.status(200).send({ message: 'success' })
}
})(req, res, next);
};
Could anyone help me with this bug or at least navigate me towards the right direction? I can't seem to find solution to my problem. Thank you all in advance!

How to automatically calculate INSERTET DATE - current date

i have a table:
CREATE TABLE IF NOT EXISTS bands (
id serial PRIMARY KEY,
name VARCHAR UNIQUE NOT NULL,
creationDate DATE not NULL,
years DATE not NULL
);
I only want to pass name and creation date. what i want is that years will return currentdate - creationDate. The problem is that I do not really know where i should correctly change my code, because im using Node project.
My code looks like this:
const express = require("express");
const app = express();
const pool = require("./db");
app.use(express.json());
// Routes
app.post("/bands", async (req, res) => {
try {
const { name, creationDate } = req.body;
const newBand = await pool.query(
"INSERT INTO bands (name, creationDate,years) VALUES ($1, $2) RETURNING *",
[name, creationDate]
);
res.json(newBand);
} catch (err) {
console.error(err.message);
}
});
app.get("/bands", async (req, res) => {
try {
const allBands = await pool.query("SELECT * FROM bands");
res.json(allBands);
console.log(allBands);
} catch (err) {
console.error(err.message);
}
});
app.get("/bands/:bandsName", async (req, res) => {
console.log(req.params);
const { bandsName } = req.params;
try {
const todo = await pool.query("SELECT * FROM bands WHERE name = $1", [
bandsName,
]);
res.json(todo.rows[0]);
} catch (err) {
console.error(err.message);
}
});
app.put("/bands/:id", async (req, res) => {
try {
const { id } = req.params;
const { name, creationDate } = req.body;
const updateTodo = await pool.query(
"UPDATE band SET name = $1, creationDate = $2 WHERE id = $3",
[name, creationDate, id]
);
res.json("Udało się, zaaktualizowane");
} catch (err) {
console.error(err.message);
}
});
app.delete("/bands/:id", async (req, res) => {
try {
const { id } = req.params;
const deleteTodo = await pool.query("DELETE FROM bands WHERE id = $1", [
id,
]);
res.json("Usunięto");
} catch (err) {
console.error(err.message);
}
});
app.listen(3000, () => {
console.log("server is listening on port 3000");
});
Can anyone tell me where should i change my code so "years" will automatically calculate without me having to put the data in postman?
const { name, creationDate } = req.body;
const d = new Date(creationDate );
const year = d.getFullYear();
Create a date object and retrieve the year would do it

How to fix sequelize connection issue while generating index.js?

I new in node.js and have some problems with sequelize-cli.
I have sequelize model and while I run the project, i get error in my index.js:
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
TypeError: require(...) is not a function
The project can't find or read this (sequelize, Sequelize.DataTypes).
My project: server.js
const express = require("express");
const productRouter = require("./routers/productRouter");
const discountRouter = require("./routers/discountRouter")
const app = express();
const PORT = process.env.PORT || 3000;
app.use(express.json());
// Запрос на таблицу с продуктами
app.use("/shop", productRouter);
// Запрос на таблицу со скидками
app.use("/shop", discountRouter);
app.listen(PORT, () => console.log("Server is working ... "));
productRouter.js
const Router = require("express");
const router = new Router();
const productController = require("../controllers/productControllers");
// Получаем все товары
router.get("/products", async (req, res, next) => {
const resultOfGetAllProducts = await productController.all();
if(resultOfGetAllProducts === Error) {
return res.sendStatus(500).json(Error);
} else {
return res.sendStatus(200).json(resultOfGetAllProducts);
};
});
// Получаем конкретный товар
router.get("/product/:id", async (req, res, next) => {
if(!req.params.id) return res.sendStatus(400).send("Product ID is not specified.");
const id = req.params.id;
const result = null;
const resultOfGetOneProduct = await productController.one(id, result);
if(resultOfGetOneProduct === Error) {
return res.sendStatus(500).json(Error);
} else {
return res.sendStatus(200).json(resultOfGetOneProduct);
};
});
// Добавляем товар
router.post("/product", async (req, res, next) => {
if(!req.body) return res.sendStatus(400).send("Product parameters are not specified.");
const product = {
product_name: req.body.product_name,
price: req.body.price,
product_description: req.body.product_description
};
const result = null;
const resultOfCreateProduct = await productController.create(product, result);
if (resultOfCreateProduct === Error) {
return res.sendStatus(500).json(Error);
} else {
return res.sendStatus(200).send("The product has been created.");
}
});
// Обновляем товар
router.put("/product/:id", async (req, res, next) => {
if(!req.params.id) return res.sendStatus(400).send("Product ID is not specified.");
if(!req.body) return res.sendStatus(400).send("Product parameters are not specified.");
const product = {
product_name: req.body.product_name,
price: req.body.price,
product_description: req.body.product_description
}
const id = {id: req.params.id};
const result = null;
const resultOfUpdateProduct = await productController.update(id, product, result);
if(resultOfUpdateProduct === Error) {
return res.sendStatus(500).json(Error);
} else {
return res.sendStatus(200).send("The product has been updated.");
};
});
// Удаляем товар
router.delete("/product/:id", async (req, res, next) => {
if(!req.params.id) return res.sendStatus(400).send("Product ID is not specified.");
const id = {id: req.params.id};
const result = null;
const resultOfDeleteProduct = await productController.delete(id, result);
if(resultOfDeleteProduct === Error) {
return res.sendStatus(500).json(Error);
} else {
return res.sendStatus(200).send("The product has been deleted.");
}
});
module.exports = router;
productControllers.js
const productModels = require("../models/productModels");
exports.all = async function getAllProducts() {
const result = await productModels.all(function(err, docs) {
if (err) {
console.log(err);
return err;
} else {
return docs;
};
});
return result;
};
exports.one = async function getOneProduct(id, cb) {
const result = await productModels.one(id, function(err, doc) {
if (err) {
console.log(err);
return err;
} else {
return doc;
}
});
cb = result;
return cb;
};
exports.create = async function createProduct(product, cb) {
const confirmationOfCreate = await productModels.create(product, function(err, result) {
if (err) {
console.log(err);
return err;
} else {
return result;
}
});
cb = confirmationOfCreate;
return cb;
};
exports.update = async function updateProduct(id, product, cb) {
const confirmationOfUpdate = await productModels.update(id, product, function(err, result) {
if (err) {
console.log(err);
return err;
} else {
return result;
}
});
cb = confirmationOfUpdate;
return cb;
};
exports.delete = async function deleteProduct(id, cb) {
const confirmationOfDelete = await productModels.delete(id, function(err, result) {
if (err) {
console.log(err);
return err;
} else {
return result;
}
});
cb = confirmationOfDelete;
return cb;
};
productModels.js
const Sequelize = require("sequelize");
const productsModel = require("./products.js");
const db = require("./index.js");
// Получаю с бд все продукты
exports.all = async function getProducts(cb) {
//const products = await db.query('SELECT * FROM products');
const products = await db.findAll({raw: true});
if(products === null) {
return cb(Error, null);
} else {
return cb(null, products);
};
};
// Получаю с бд конкретный продукт
exports.one = async function getOneProduct(id, cb) {
//const getOneQuery = 'SELECT * FROM product where id = $1';
//const getDiscount = 'SELECT * FROM discounts where product_id = $1';
//const curDiscount = await Discount.findOne({where: id});
const product = await db.findAll({where: {id: id}});
const productDiscount = await Discount.findAll({where: {product_id: id}});
const priceWithDiscount = product.price - (product.price * ((productDiscount.discount)/100));
if (product === null) {
return cb(Error, null);
} else if(productDiscount === null) {
return cb(null, product)
} else {
product.price = priceWithDiscount;
const result = product;
return cb(null, result);
};
};
// Создаю в бд продукт
exports.create = async function createProduct(product, cb) {
// const createQuery = 'INSERT INTO product (product_name, price, product_description) values ($1, $2, $3) RETURNING *';
// const arrayQuery = [product.product_name, product.price, product.product_description];
// const newProduct = await db.query(createQuery, arrayQuery);
const newProduct = await db.create(product);
if(newProduct === null) {
return cb(Error, null);
} else {
return cb(null, newProduct);
};
};
// Обновляю в бд конкретный продукт
exports.update = async function updateProduct(id, newData, cb) {
// const updateQuery = 'UPDATE product set product_name = $1, price = $2, product_description = $3 where id = $4 RETURNING *';
// const arrayQuery = [newData.product_name, newData.price, newData.product_description, id];
const product = await db.update(newData, {where: id});
if(product === null) {
return cb(Error, null);
} else {
return cb(null, product);
};
};
// Удаляю в бд конкретный продукт
exports.delete = async function deleteProduct(id, cb) {
//const deleteQuery = 'DELETE FROM product where id = $1';
const product = await db.destroy({where: id});
if(product === null) {
return cb(Error, null);
} else {
return cb(null, product);
};
};
product.js
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class products extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
}
};
products.init({
product_name: DataTypes.STRING,
price: DataTypes.NUMBER,
product_description: DataTypes.STRING
}, {
sequelize,
modelName: 'products',
});
return products;
};
index.js
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
Also i have migration's and config's files.
What I must to do to issue this errors or another problems?
Move productModels.js to 'repository' directory
because, there is no 'default' export in this file
And, db operation file cannot sit in models folder
I fixed that, and upload to git https://github.com/nkhs/node-sq-stack.git

Cannot read property 'count' of undefined Express API

When i call Create Option api it is working fine but when i call list api get error: Cannot read property 'count' of undefined Express (Node + MongoDB) API.here is my Option Controller File code.
i have Log DB.ProductDoption ,getting result but count function not working.
const _ = require('lodash');
const Joi = require('joi');
exports.create = async (req, res, next) => {
try {
const validateSchema = Joi.object().keys({
name: Joi.string().required(),
key: Joi.string().required(),
description: Joi.string().allow(['', null]).optional(),
options: Joi.array().items(Joi.object().keys({
key: Joi.string().required(),
displayText: Joi.string().required()
})).required()
});
const validate = Joi.validate(req.body, validateSchema);
if (validate.error) {
return next(PopulateResponse.validationError(validate.error));
}
const key = Helper.String.createAlias(req.body.key);
console.log(DB.ProductDoption);
const count = await DB.ProductDoption.count({ key });
if (count || validate.value.key === '_custom') {
return next(PopulateResponse.error({
message: 'Please add unique name for key'
}));
}
const option = new DB.ProductDoption(validate.value);
await option.save();
res.locals.option = option;
return next();
} catch (e) {
return next(e);
}
};
exports.list = async (req, res, next) => {
const page = Math.max(0, req.query.page - 1) || 0; // using a zero-based page index for use with skip()
const take = parseInt(req.query.take, 10) || 10;
try {
const query = Helper.App.populateDbQuery(req.query, {
text: ['name', 'key', 'description']
});
const sort = Helper.App.populateDBSort(req.query);
const count = await DB.ProductDoption.count(query);
const items = await DB.ProductDoption.find(query)
.collation({ locale: 'en' })
.sort(sort).skip(page * take)
.limit(take)
.exec();
res.locals.optionList = {
count,
items
};
next();
} catch (e) {
next(e);
}
};
collection.count is deprecated, and will be removed in a future version. Use Collection.countDocuments or Collection.estimatedDocumentCount instead

Why is this mongoose 'findOne' query always returning null?

I am trying to find a specific document with mongoose in my Cosmosdb with this query described below.
const mongoose = require('mongoose');
var ObjectID = require('mongodb').ObjectID
const keys = require('../config/keys');
const Item = mongoose.model('items');
const uploadToBlob = async (containerName, blobName, json, id) => {
console.log('id', id)
Item.findOne({ _id: id }, (foundItem) => {
console.log(foundItem)
});
console.log('here')
Item.findOneAndDelete({ name: blobName });
};
I am successfully able to find the document when querying like this below.
const scanMongo = () => {
Item.find({
_id: {
$gt: ObjectID.createFromTime(Date.now() / keys.mongoPurgeInterval)
}}, (err, foundItems) => {
if(err) {
console.log("Oops", err);
return;
}
foundItems.forEach(item => {
JSON.stringify(item)
const blobName = item.name;
json = "'"+item+"'"
const id = item._id
uploadToBlob(keys.containerName, blobName, json, id);
});
});
}
This is what the object I'm looking for looks like when pulled from the query above.
[ { _id: 5cabd5c6e16288230cba2cf6, name: 'test', value: 1, __v: 0 } ]
For kicks, here my model.
const mongoose = require('mongoose');
const { Schema } = mongoose;
const itemSchema = new Schema({
name: String,
value: Number,
});
mongoose.model('items', itemSchema);
I'm befuddled. Any help would be bawler. Thanks!!!
Yeah, the first parameter is supposed to catch the error.
Item.findOne({ _id: id }, (error, foundItem) => {
console.log(foundItem)

Categories

Resources