Foreign Key relationship in Mongoose with customized key - node.js

I am kinda new to MongoDB and nextjs space. I have 2 schemas :
User
Fav Dishes
Schema for user is :
import mongoose from 'mongoose'
require('mongoose-type-url');
const UserSchema = new mongoose.Schema({
name: { type: String, unique: true}
address: {type: String},
},{ timestamps: {} })
UserSchema.pre("save", function (next) {
let brand = this;
user.name = user.name.replace(/ /g,"_")
next();
})
Another schema is
const FavDish = new mongoose.Schema({
name: String,
user: {type: mongoose.Schema.Types.ObjectId, ref : 'User'})
So the reference in FavDish collection want to use is userName instead mongo created ObjectID. and while populating the data for FavDish get the details for user as well. How can i achieve this? please help me.

So, first of all, if the relationship between the Schemas are 1to1, consider embedding the favDish inside the user Schema and not referencing (each user has a name, an address and a favDish name).
So the userSchema will look like:
const UserSchema = new mongoose.Schema({
name: { type: String, unique: true}
address: String,
fevDish: String
},{ timestamps: {} })
If you want to keep it like the way you wanted (with two schemas and referencing) you will need to populate after finding the fevDish:
const populatedDish = await FavDishModel.findOne({name: 'pasta'}).populate('user');
/**
* populatedDish - {
* name: 'pasta',
* user: {
* name: 'Justin',
* address: 'NY'
* }
* }
*
*/
this way while finding the dish you want, mongoose will put the user object instead of the _id of it.
Hope that helps.

Related

Mongo - I cannot populate field in referenced collection without using populate and populated together - why?

I want to populate all items inside an array from the collection I reference.
It never works and poplute doesnt seem to run unless I populate and then use .populated on the result. I dont understand what this is?
const userSchema = new mongoose.Schema({
email: String,
following: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Product'
}]
});
const productSchema = new mongoose.Schema({
name: String,
price: String
...
});
const products = await User.findOne({ _id: req.user._id }).populate('following')
const productsAgainPopulated = products.populated('following');
only productsAgainPopulated will actually return the followed products.
products will only return me the user

Error when using _id as a property type in a Mongoose Schema

I am learning MongoDB and mongoose at the moment. I have a Archive and a User schema in mongoose:
archive.js
var mongoose = require('mongoose');
var User = require('../users/user');
var notesSchema = new mongoose.Schema({
author: User.userId,
text: String,
files:[String]
});
var archiveSchema = new mongoose.Schema({
name: String,
priority: String,
deadline: Date,
status: String,
assigned_memnbers: [User.userId],
notes: [notesSchema],
});
archiveSchema.virtual('archiveId').get(function() {
return this._id;
});
module.exports = mongoose.model('Archive', archiveSchema);
user.js:
var mongoose = require('mongoose');
var userSchema = new mongoose.Schema({
username: String,
mail: String,
bio: String,
password: String
});
userSchema.virtual('userId').get(function() {
return this._id;
});
module.exports = mongoose.model('User', userSchema);
When I run my server i get the error
TypeError: Invalid value for schema path `author`, got value "undefined"
The the problem comes from author: User.userId, but I don't know how to make a reference between the two tables.
For reference, here is what my complete db design more or less looks like:
Any input on how to solve this problem or improve the overall design is welcome. Thanks you.
I think what you're talking about is a reference to other collection:
author: { type: Schema.Types.ObjectId, ref: 'User' }
and
assigned_members: [{ type: Schema.Types.ObjectId, ref: 'User' }]
should work fine.
Source: Mongoose population
I faced the same issue.I had imported a module, It was just not exporting from another module. so I have added:
exports.genreSchema = genreSchema;

mongoose autoincrement counter per unique value

I have the two models, entity and post, and I'm trying to create an auto incremented counter on post for each unique entity:
//entity
var entitySchema = mongoose.Schema({
name: String,
counter: Number,
});
//post
var postSchema = mongoose.Schema({
test: String,
entity: {
type: Schema.Types.ObjectId,
ref: 'entity'
},
ticketNumber: Number //this needs to auto increment starting at zero PER user, so entity A has a 1+, entity 2 has a 1+, etc
});
I can have a sequence on entity, check it every time I create a post and use it, but that could possibly have duplicates.
I found a post suggesting an even on pre post'save', but that wouldn't be unique to each entity, just unique overall.
Any way to get this working on the model itself / a better way of doing this?
You can use the npm package called mongoose-auto-increment.
Your connection would look like this:
var autoIncrement = require('mongoose-auto-increment');
var connection = mongoose.connect('YOUR CONNECTION');
autoIncrement.initialize(connection);
your Schema would look like this:
var postSchema = mongoose.Schema({
test: String,
entity: {
type: Schema.Types.ObjectId,
ref: 'entity'
},
ticketNumber: Number
});
postSchema.plugin(autoIncrement.plugin, { model: 'NAME YOUR MODEL', field: 'ticketNumber', startAt: 0, incrementBy: 1 });

mongoose-schema - are both children array + parent doc's ID necessary?

I'm using a couple of one-to-many models and was wondering what the advantage of having both an array of "children" ObjectID()s and a "parent" model's ObjectID() in the child is. For example:
// a client will have a new card every ten visits
var ClientSchema = new Schema({
first_name: String,
last_name: String,
email: String,
cards: [] // ObjectID()s, <--- is this necessary?
});
var CardSchema = new Schema({
client: ObjectID(), // <--- or is this enough?
visits: []
});
I think the client: ObjectID() should do the trick in most cases, specially with the Population options Mongoose offers.
It suffices to store the reference ObjectId in one of the documents.
As you can read in the documentation or in this answer, the reference field needs a type and a ref. The name of field is arbitrary. Once you have done this and registered your models, you can use the models to populate your queries.
var clientSchema = new Schema({
first_name: String,
last_name: String,
email: String
});
var cardSchema = new Schema({
client: {
type: Schema.Types.ObjectId,
ref: 'client'
}
});
// models
var Card = mongoose.model('Card', cardSchema);
var Client = mongoose.model('Client', clientSchema);
Yet, it could be helpful to store an array of ObjectId's. However, this also creates a huge window for mistakes. A mismatch of foreign key and primary key, in SQL dialect. You can always do a count query if you need to count. I would say, do either the above or do this:
var clientSchema = new Schema({
first_name: String,
last_name: String,
email: String,
cards: [
{
type: Schema.Types.ObjectId,
ref: 'card'
}
]
});
var cardSchema = new Schema({
card_name: String
});
// models
var Card = mongoose.model('Card', cardSchema);
var Client = mongoose.model('Client', clientSchema);

Accessing mongoose schema array with body-parser

Here is an example schema:
var schema = mongoose.Schema;
var userSchema = new schema ({
username: {type: String},
hobby: [{
indoor: {
type: {type: String},
description: {type: String}
},
outdoor: {
type: {type: String},
description: {type: String}
}
}]
});
module.exports = mongoose.model('User', userSchema);
So, a very simple schema. It asks for a user name, and then it asks for a user to list their hobbies, and is split between indoor and outdoor hobbies, and inside of an array.
Using body-parser, I could get to a user name in a form input like this:
var user = new User();
user.username = req.body.username;
That's simple enough. But how do I get to the hobbies inside of the array? I've tried doing:
user.hobby.indoor.type = req.body.type
But this doesn't work; it just gives me an error. Any help would be appreciated.
The following code will help you access your key properly. As hobby is an array, you need to provide an index for fetching its objects. Dot notation works with objects
user.hobby[0].indoor.type
Js Fiddle: https://jsfiddle.net/x18nyd2e/
So I did end up finding the answer to my problem. Here is an example of what to do:
var user = new User();
user.username = req.body.username;
user.hobby = {{
indoor: {
type: req.body.type,
description: req.body.description
}
}];
And that's how you can get to a property inside of an array.

Resources