Mongoose .pull not deleting subdocument - mongodb

I'm trying to remove a product from a category using mongoose .remove from these other questions but none seem to work
Remove sub-document from Mongo with mongoose
But nothing is happening and I only get back the same thing unedited
Category Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Product = require('./Product');
const CategorySchema = Schema({
_id: Schema.Types.ObjectId,
categoryName: {
type: String,
required: true,
},
categoryDescription: String,
productList: [Product],
});
mongoose.model('Category', CategorySchema);
Products Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ProductSchema = Schema({
productName: {
type: String,
required: true,
},
productDescription: String,
categories: { type: Schema.Types.ObjectId, ref: 'Category' },
});
mongoose.model('Product', ProductSchema);
My express route to handle deleting of the subdocument
app.delete('/api/category-with-product/:categoryId', (req, res) => {
const categoryId = req.params.categoryId;
const { productId } = req.body;
Category.findById(categoryId)
.then((category) => {
category.productList.pull({ _id: productId });
return category.save();
})
.then((newCategory) => {
res.send(newCategory);
});
});
My expected outcome is for this is to just remove the product in the productList array
{
_id: 5c5b990d56b3f61ce3736e6f,
categoryName: 'A new category name',
description: 'description',
productList:[
{ _id: 5c6e4b5114333b25f8e9d737,
productName: 'test',
productDescription: 'test'
}
],
}

Could you please try this:
const ObjectId = mongoose.Types.ObjectId;
function funcName() {
return new Promise((resolve, reject) => {
db.category.update(
{ },
{ $pull: { productList: { _id: ObjectId(productId) } } },
{ multi: true }
)
.then((result) => resolve())
.catch((err) => reject(err));
});
}
You can also try Async/Await during database operations.

Related

How can I see the products per each category with mongoose

this is my schema for storing products using mongoose as below.
const mongoose = require("mongoose");
const mongoosePaginate = require("mongoose-paginate-v2");
const productSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: {
type: String,
required: true,
},
category: {
type: mongoose.Schema.Types.ObjectId,
ref: "Category",
},
productImage: {
type: String,
required: true,
},
description: {
type: String,
},
createdAt: {
type: Date,
default: new Date(),
},
deletedAt: {
type: Date,
},
});
productSchema.plugin(mongoosePaginate);
const productModel = mongoose.model("Product", productSchema, "Product");
module.exports = productModel;
and this how I have the schema for storing categories that products are related to
const mongoose = require("mongoose");
const categorySchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
product: { type: mongoose.Schema.Types.ObjectId, ref: "Product" },
});
const categoryModel = mongoose.model("Category", categorySchema, "Category");
module.exports = categoryModel;
What I don´t know is how to populate my controller.
getAll: async (req, res) => {
const limitPage = parseInt(req.query.limit, 10) || 10;
const pageChange = parseInt(req.query.page, 10) || 1;
Product.paginate({}, { limit: limitPage, page: pageChange })
.then((result) => {
return res.status(200).json({
message: "GET request to all getAllProducts",
dataCount: result.length,
result: result,
});
})
.catch((err) => {
console.log(err);
res.status(500).json({
error: err,
});
});
},
Please help, I don´t understand why it not being populated and how to see the categories displayed with the categorie they belong to.
You should probably include populate in your query like so:
...
Product.paginate({}, { limit: limitPage, page: pageChange }).populate('category')
...
Note: Are you sure you want to have a 1-1 relation between products and categories. Because this is what you achieve if you set the relation like you did on both schemas. If yes, you should find a way to ensure that this 1-1 relation is enforced each time you save or update objects.

mongoose .populate() is not populating even with variable set to ObjectId

Here is my model for "product" schema:
const productSchema = new Schema({
productName: String,
productCategory: {
type: Schema.Types.ObjectId,
ref: "category",
},
productPrice: Number,
productImageUrl: String,
});
Here is the router for the GET method:
router.get("/", async (req, res) => {
try {
const products = await ProductModel.find().populate("category");
res.status(200).json({ erorr: false, products });
} catch (err) {
res.status(500).json({ error: true, err });
}
});
What I actually get is this:
"error": false,
"products": [
{
"_id": "6009f4bfd397734920c93ce8",
"productName": "Milk",
"productCategory": "6009d244332f2f22c40f90b4",
"productPrice": 8,
"productImageUrl":""
In Mongo Compass I can see that "productCategory" is set with ObjectId value.
Any ideas what am I doing wrong?
Thanks!
Try this one:
const mongoose = require('mongoose');
const Types = mongoose.Schema.Types;
const productSchema = new Schema({
productName: String,
productCategory: {
type: Types.ObjectId,
ref: "category",
},
productPrice: Number,
productImageUrl: String,
});
const products = await ProductModel.find({}).populate({path:"productCategory"});
you should put the key that has ref to populate like this:
const products = await ProductModel.find().populate("productCategory");

How to insert auto increment number in mongoose

Tried to insert auto increment number for serial number in mongodb using mongoose and nodejs but not working.Where i want to update my code to find solution.If anyone knows please help to find solution.
subs.model.js:
const mongoose = require('mongoose');
var subscriberSchema = new mongoose.Schema({
_id: {type: String, required: true},
email: {
type: String
}
}, {
versionKey: false,
collection: 'subscribers'
});
module.exports = mongoose.model('Subscribers', subscriberSchema);
data.controller.js:
module.exports.subscribeMail = (req, res, next) => {
var subscribeModel = mongoose.model("Subscribers");
var subscribemailid = req.query.email;
var subscribe = new subscribeModel({
email: subscribemailid
});
var entitySchema = mongoose.Schema({
testvalue: { type: String }
});
subscribe.save(function(error, docs) {
if (error) { console.log(error); } else {
console.log("subscribe mail id inserted");
console.log(docs)
res.json({ data: docs, success: true });
}
});
entitySchema.pre('save', function(next) {
var doc = this;
subscribe.findByIdAndUpdate({ _id: 'entityId' }, { $inc: { seq: 1 } }, function(error, counter) {
if (error)
return next(error);
doc.testvalue = counter.seq;
next();
});
});
};
If i use above code inserting data into mongodb like below:
_id:5f148f9264c33e389827e1fc
email:"test#gmail.com"
_id:6f148f9264c33e389827e1kc
email:"admin#gmail.com"
But i want to insert like this
_id:5f148f9264c33e389827e1fc
serialnumber:1
email:"test#gmail.com"
_id:6f148f9264c33e389827e1kc
serialnumber:2
email:"admin#gmail.com"
You can use this plugin: https://www.npmjs.com/package/mongoose-auto-increment
First you need to initialize it after creating Mongoose connection:
const connection = mongoose.createConnection("mongodb://localhost/myDatabase");
autoIncrement.initialize(connection);
Than in your subs.model.js file:
const mongoose = require('mongoose');
const autoIncrement = require('mongoose-auto-increment');
var subscriberSchema = new mongoose.Schema({
_id: {type: String, required: true},
email: {
type: String
}
}, {
versionKey: false,
collection: 'subscribers'
});
subscriberSchema.plugin(autoIncrement.plugin, {
model: 'Subscribers',
field: 'serialnumber'
});
module.exports = mongoose.model('Subscribers', subscriberSchema);

Query wont return data from relationship

I'm following this video series.
Here i have problem with getting data about user who created the event in following script
here's my app.js
const express = require('express');
const bodyParser = require('body-parser');
const graphqlHttp = require('express-graphql')
const { buildSchema } = require('graphql');
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const Event = require('./models/event');
const User = require('./models/user');
const app = express();
const conString = `mongodb+srv://${process.env.MONGO_USER}:${process.env.MONGO_PASSWORD}#clusterpl-qiufl.mongodb.net/${process.env.MONGO_DB}?retryWrites=true&w=majority`
app.use(bodyParser.json());
app.use(
'/graphql',
graphqlHttp({
schema: buildSchema(`
type Event {
_id: ID!
title: String!
description: String!
price: Float!
date: String!
creator: User!
}
type User {
_id: ID!
email: String!
password: String!
createdEvents: [Event!]
}
input UserInput {
email: String!
password: String!
}
input EventInput {
title: String!
description: String!
price: Float!
date: String!
}
type RootQuery {
events: [Event!]!
}
type RootMutation {
createEvent(eventInput: EventInput): Event
createUser(userInput: UserInput): User
}
schema {
query: RootQuery,
mutation: RootMutation
}
`) ,
rootValue: {
events: () => {
return Event.find().populate('creator')
.then(events => {
console.log(events)
return events.map(event => {
console.log(event)
return {
...event._doc,
_id: event.id
};
});
})
.catch(err => {
throw err;
})
},
..
},
graphiql: true
})
);
mongoose.connect(conString, {useNewUrlParser: true}).then(
() => {console.log('Success !')},
err => { console.log(err) }
)
app.listen(3000);
user.js and event.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema({
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
createdEvents: [
{
type: Schema.Types.ObjectId,
ref: 'Event'
}
]
});
module.exports = mongoose.model('User', userSchema)
const mongoose = require('mongoose');
const Schema = mongoose.Schema
const eventSchema = new Schema({
title: {
type: String,
required: true
},
description: {
type: String,
required: true
},
price: {
type: Number,
required: true
},
date: {
type: Date,
required: true
},
creator: [
{
type: Schema.Types.ObjectId,
ref: 'User'
}
]
});
module.exports = mongoose.model('Event', eventSchema);
once i submit this graphql query
query{
events {
creator {
email
}
}
}
returns "message": "Cannot return null for non-nullable field User.email.",
I'm completly new to graphql and any answer would be much appreciate.
maybe this might helps someone else, i don't know what happens there but i got expected results, by adding
const user = userId => {
return User.findById(userId).then(user => {
return { ...user._doc, _id: user.id };
})
.catch(err => {
throw err;
});
}
method and used it in event resolver function like this
events: () => {
return Event.find()
.populate('creator')
.then(events => {
return events.map(event => {
console.log('ev',event._doc)
return {
...event._doc,
_id: event.id,
// creator: {
// ...event._doc.creator._doc,
// _id: event._doc.creator.id
// }
creator: user.bind(this, event._doc.creator)
};
})
})
.catch(err => {
throw err;
})
},

Update mongodb document using discriminators

I've got a question about discriminators and mongoose/mongodb. I would like to understand how I can update one document which contains 2 properties whichs are array of discriminators.
Here my mongoose models :
const mongoose = require('mongoose');
const carSchema = require('./car');
const continentalWheelSchema = require('./wheel/continental');
const michelinWheelSchema = require('./wheel/michelin');
const CarSchema = new mongoose.Schema({}, { discriminatorKey: 'type', _id: false } );
const WheelSchema = new mongoose.Schema({}, { discriminatorKey: 'type', _id: false } );
const ClientParkSchema = new mongoose.Schema({
customer: { type: String, required: true },
created_at: { type: Date, default: Date.now },
updated_at: { type: Date, default: Date.now },
cars: [CarSchema],
wheels: [WheelSchema]
});
ClientParkSchema.path('cars').discriminator('break', carSchema);
ClientParkSchema.path('wheels').discriminator('continental', continentalWheelSchema);
ClientParkSchema.path('wheels').discriminator('michelin', michelinWheelSchema);
module.exports = {
ClientPark: mongoose.model('client_park', ClientParkSchema, 'client_park')
};
/////////////////////// CAR SCHEMA ////////////////////////
const mongoose = require('mongoose');
const CarSchema = new mongoose.Schema({
brand: { type: String, required: true },
model: { type: String, required: true },
}, { _id: false } );
module.exports = CarSchema;
/////////////////////// CONTINENTAL WHEEL SCHEMA ////////////////////////
const mongoose = require('mongoose');
const ContinentalWheelSchema = new mongoose.Schema({
model: { type: String, required: true }
}, { _id: false } );
module.exports = ContinentalWheelSchema;
/////////////////////// MICHELIN WHEEL SCHEMA ////////////////////////
const mongoose = require('mongoose');
const MichelinWheelSchema = new mongoose.Schema({
price: { type: number, required: true},
model: { type: String, required: true },
season: { type: String, required: true }
}, { _id: false } );
module.exports = MichelinWheelSchema;
mongodb query :
db.client_park.updateOne({_id: ObjectId('5d3865a4e56473518adabd35'), "car.type": 'break',"wheel.type": "michelin"}, {$set: {"car.$.brand": 'Ford',"wheel.$.price": 100,"wheel.$.season": "summer"}})
The query seems to work but the document is not updated. So I would like to know how could I update my document by discriminators (if there are exists).
Thank you very much !
EDIT :
The document I want to update :
{
"_id":"5d39a19e2376c7089ec7707b",
"customer":"5d0757aa4b6620003335aff2",
"cars":[
{
"type":"break",
"brand":"Ford"
}
],
"created_at":"2019-07-25T12:33:34.799Z",
"updated_at":"2019-07-25T12:33:34.799Z",
"_v":0
}