Foreign key composed from multiple models - javascript

I am using mongo and mongoose and I am trying to model my app.
I have the following models: ProductA, ProductB and ProductChat.
Each Product can have many Chats. Each chat is related to one and only product (A or B).
I'd like ProductChat to have a reference to the relevant product document. I thought about adding productType, productId fields to ProductChat:
const ProductChatSchema = new Schema({
...
...
productType: {
type: 'String',
required: true,
enum: [ 'A', 'B' ]
},
product: {
type: Schema.Types.ObjectId,
required: true,
ref: '???' // Ref to what?
},
...
...
});
But I don't know what to put on 'ref'...
I'd like to avoid adding productAId, productBId fields on ProductChat because there might be many products.
Any idea how to do it correct?

As there are many products, give ProductChat ref to ProductsA(B, C..) collection in an array.
const productA = new Schema({
ProductChatIds: [{
type: Schema.Types.ObjectId,
ref: 'ProductChat'
}]
});
const productB = new Schema({
ProductChatIds: [{
type: Schema.Types.ObjectId,
ref: 'ProductChat'
}]
});

ref field means in which collection the id mentioned is gonna be searched for. So, you have to refer to the collection.
For example:
var postSchema = new Schema({
name: String,
postedBy: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
dateCreated: Date,
comments: [{body:"string", by: mongoose.Schema.Types.ObjectId}],
});
Then make your model:
var Post = mongoose.model('Post', postSchema);

Related

How to query a mongo document using mongoose?

MongoDB documents contain an array of objects and what is the best way to query those documents if I want to find and remove an object from an array with some specific value;
Here is an example of the document schema
const mongoose = require("mongoose");
const LibrarySchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
},
books: [
{
type: new mongoose.Schema({
bookName: {
type: String,
required: true,
},
chapterReading: {
type: Number,
default: 1,
required: true,
},
}),
},
],
});
const Library = mongoose.model("Library", LibrarySchema);
exports.Library = Library;
If I want to find and remove a book with some bookName
Use $pull
Example :
Library.update({}, { $pull: { books: { bookName: "Yourbookname" } } })

Mongoose populate nested element inside of multiple arrays

I have the following schema:
const userSchema = new Schema({
...,
categories: [
{
name: {
type: String,
required: true
},
products: [
{
type: mongoose.Types.ObjectId,
required: false,
ref: 'Product'
}
]
}
],
...
}
I want to get all the products a user have.
I have seen more questions about this topic but I don't get it to work.
If you entered your data correctly you can do like this:
let result = await User.findById(id).populate("categories.products").lean()

How to populate field in all objects of an array response?

I have a User model:
const userSchema = new Schema({
username: String,
email: String,
_id: generated
})
and a Project model:
const projectSchema = new Schema({
owner: { type: Schema.Types.ObjectId, ref: 'User' },
name: String,
_id: generated
})
I am using a request to get all projects, and would like to then populate the 'owner' field of each project with the corresponding user (or, even better, their username)
Project.find()
.populate('owner')
.then((allProjects) => {
console.log(allProjects);
res.status(200).json(allProjects);
})
The response from the find(), as seen in the console.log() is an array of objects, on which populate seems to have had no effect:
[{
_id: 4kal5mah5lam6la2lam40am3,
owner: 28eqo29roqi5lqmdka91ma01,
name: Project1
},
{
_id: 0akm40am593na7n4fnau25a,
owner: 85jan5l60oq23la1p07d8q2,
name: Project2
}]
I've tried many things with the populate call and its parameter but to no effect. The code runs, just doesn't populate the field. Any ideas?
Many thanks!

Delete only those, which have no Entry in first table corresponding to the second table

var productSchema = Schema({
product_code: String,
name: {
type: String,
required: true
},
description: String,
category:{
type: String,
ref: 'Product_Category'
},
umo: String,
threshold: {
type:Number,
default: 0
},
image: String,
isactive: {
type: Boolean,
default: true
}
});
var product_categorySchema = Schema({
isactive: {
type: Boolean,
default: true
},
name: {
type: String,
required: true
},
description: String
});
I have these two schema I am deleting from category, but if I have data corresponding to that category in product table then that category should not be deleted. Can anyone help?
it should look like something like this :
// Function which delete the category behind the given _id
async function deleteCategory(idCategory) {
// check if there is a product related to the category
const ret = await product_schema.findOne({
category: idCategory,
});
// if there is, return an error
if (ret) throw new Error('Cannot delete the category');
// else do delete the category
return product_category_schema.remove({
_id: idCategory,
});
}
Also you have to know that :
category:{
type: String,
ref: 'Product_Category'
},
is not the right way to setup a reference; it should be an ObjectId not a String
const {
Schema,
} = mongoose;
category:{
type: Schema.Types.ObjectId,
ref: 'Product_Category'
},
Firstly, please update "type" property of "category" field in product schema like this:
category:{
type: Schema.Types.ObjectId,
ref: 'Category' // model name
}`
and declare model like this :
var Product = mongoose.model('Product', productSchema );
then use "distinct" query and "$nin" query-operator to delete category which are not referenced by product schema like this :
Product.find().distinct('category').then((data)=>{
Category.deleteMany({_id: {$nin: data}}).then(del => {
console.log("deleted",del)
})
})

How to find an object, where element in an array does not match another field in that schema?

I am using mongoose 4.13.11 and am trying to find an element in an array where the 'last_message_read.messageId' does not equal the 'last_message field'. Here is the schema I am working with:
conversationSchema = new Schema{(
last_message: {type: Schema.Types.ObjectId, ref: "Message"},
members: [{
type: Schema.Types.ObjectId,
ref: "User"
}],
last_message_read: [{
user_id: {type: Schema.Types.ObjectId, ref: 'User'},
message: {type: Schema.Types.ObjectId, ref: "Message"}
}],
)}
And this is my attempted query:
const user_id = ObjectId();
conversationModel.find(
{members: user_id},
{ $expr: { $where : "this.last_message != this.last_message_read.$.message && this.last_message_read.$.user_id == user_id"} },
function(err, conversations){})
The problem is however I could not find anywhere in the docs that allowed such as a query and the closest I got was using $expr and $where. For example I am not sure I can include the && operation nor the user_id inside the quote.
Any thoughts of how to perform this type of query would be great. Thanks.

Categories

Resources