Mongoose reference sub-document - node.js

is it possible to reference sub-document in mongoose? I want connect created soldier with enemy or player. In my case is easier to insert enemies into GameSchema than creating new model, but I don't really know, if I am able to make "belongsTo" as displayed below.
And my second question, is it possible to reference like in /* commented code */ ?
var GameSchema = new Schema({
...
enemies: [{
level: {type: Number, default: 0},
position: {...},
/*soldiers: [{
type: Schema.ObjectId,
ref: 'Soldier'
}],*/
}],
...
});
var SoldierSchema = new Schema({ // soldier unit
....
belongsToEnemy {
type: Schema.ObjectId,
ref: 'Game.enemies',
required: false
},
belongsToPlayer {
type: Schema.ObjectId,
ref: 'Player',
required: false
},
...
});
module.exports = mongoose.model('Game', GameSchema);
module.exports = mongoose.model('Soldier', SoldierSchema);

Related

Is there a way to pass user Id to schema?

I have a user schema and an exam schema, i wanted to pass the id of the user to the schema of the exam
const ExamSchema = new mongoose.Schema({
-----> _id: [{
class: { type: String, required: true },
module: { type: Number,required:true },
date: {type: Date, required: true }
}]
Where it says _id - i wanted it to be the id of the user! Should i do it like this or add the exams schema on the user schema? Like this?
const UserSchema = new mongoose.Schema({
username: { type: String, require: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
active: { type: Boolean, default: true },
exam: [{
class: { type: String, required: true },
module: { type: Number,required:true },
date: {type: Date, required: true }
}]
});
Check Mongoose "Populate"
https://mongoosejs.com/docs/populate.html
A part from the docs,
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const personSchema = Schema({
_id: Schema.Types.ObjectId,
name: String,
age: Number,
stories: [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
const storySchema = Schema({
author: { type: Schema.Types.ObjectId, ref: 'Person' },
title: String,
fans: [{ type: Schema.Types.ObjectId, ref: 'Person' }]
});
const Story = mongoose.model('Story', storySchema);
const Person = mongoose.model('Person', personSchema);
So far we've created two Models. Our Person model has its stories field set to an array of ObjectIds. The ref option is what tells Mongoose which model to use during population, in our case the Story model. All _ids we store here must be document _ids from the Story model.
In your case just make a user_id in Exam Schema and refer to id of User Schema
const ExamSchema = new mongoose.Schema({
user_id: {type: Schema.Types.ObjectId, ref: 'User' },
class: { type: String, required: true },
module: { type: Number,required:true },
date: {type: Date, required: true }
})

Embedding another mongoose schema

I'm trying to embed a model in a mongoose schema. Here's what I have:
const People = {
userId: {
type: mongoose.Schema.Types.objectId,
required: true,
ref: 'User'
},
locationId: {
type: mongoose.Schema.Types.objectId,
required: true,
ref: 'Location'
},
};
const Person = mongoose.model(
'Person',
new mongoose.Schema({
...People,
gender: {
type: String
}
})
);
const shmanian = await new Person({gender: 'other', userId:'someUserId', locationId: 'someLocationId'}).save();
The response I get is {gender: 'other'}
The problem is that people doesn't get populated when I create Person.
You should embed an array of "Person" inside a model "People". For example,
const Schema = require("mongoose").Schema;
const model = require("mongoose").model;
const Person = new Schema({
userId: {
type: mongoose.Schema.Types.objectId,
required: true,
ref: 'User'
},
locationId: {
type: mongoose.Schema.Types.objectId,
required: true,
ref: 'Location'
},
});
const People = new Schema({
person: [Person]
});
module.exports = model("People", People);
Here, everytime you create a new Person, you can add it to the People model which contains an array of Person objects.
Not a mongoose Problem.
People is undefined when you create the Object Person.
Thus it doesn't get populated.
Try switching both assignments.

How to display INFINITELY nested comments from mongodb

so each comment is its own document. is this how i nest comments in each other, when a user replies to one?
and if something is nested lets say as much as 10 deep in replies, how do I do a for loop to loop through it all?
var RK = mongoose.Schema.ObjectId;
var CommentSchema = Schema({
body: {type: String},
chapterId: {type: RK, ref: 'Chapter'},
by: {type: RK, ref: 'User'},
children: [{
type: RK,
ref: 'Comment'
}]
}, {timestamps: true});
let dependencySchema = mongoose.Schema({
dependencyComment: {
type: mongoose.Schema.Types.ObjectId,
required: false
},
dependencyAuthor: {
type: mongoose.Schema.Types.ObjectId,
required: false
}
});
let CommentSchema = mongoose.Schema({
//Rest of you schema
children: [{
type: mongoose.Schema.Types.ObjectId,
ref: [dependencySchema]
}]
}, {timestamps: true});
this way you nest the comment to N-th Level

How to remove left-over ObjectId?

The problem is:
I have a collection of photos schema and likes schema, and inside photos there is an array of like ObjectIds called likeArray which is used to populate data from likes colletion.
But when i delete a like from likes collection, the ObjectId of that like in the likeArray still exists.
I tried to find the index of like._id in the likeArray and use likeArray.splice(index, 1) but couldn't work.
Can someone know the solution?
Here's the photo schema:
var Photo = mongoose.model('Photo', new mongoose.Schema({
photo_url: String,
photo_description: String,
user:{
id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
},
username: String,
profile_photo: String
},
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'comment'
}
],
likes: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'like'
}
],
created_at: {type: Date, default: Date.now}
}));
Here's the Like schema:
var Like = mongoose.model('Like', new mongoose.Schema({
user_id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
},
photo_id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'photo'
},
created_at: {type: Date, default: Date.now}
}));
Instead of splice you can use $pull operator. Here's how it'd look in mongo shell.
db.likes.remove({_id: like_oid});
db.photos.update({likes: like_oid}, {$pull: {likes: like_oid}}, { multi: true });

Mongoose JS: Create a reference in one document to an embedded document in another document

I'm using Node / Mongoose / MongoDB and trying to build a polling application. A key need is to track how a single user's responses to the same poll changes over time (they take the same poll over and over).
I have a user model:
var UserSchema = new Schema({
...
})
I'm embedding Questions in my poll documents because I'm almost always going to need the questions when I request a poll.
var QuestionSchema = new Schema({
text: { type: String, required: true }
})
var PollSchema = new Schema({
name: { type: String, required: true },
questions: [QuestionSchema]
})
module.exports = mongoose.model('Poll', PollSchema);
// Know this is unnecessary, but read the following to see why I'm doing this
module.exports = mongoose.model('Question', QuestionSchema);
Here's my confusion:
My users will be taking the same poll multiple times. Accordingly, I'm creating an "AnswerHistory" which contains each "Answer" by a single user to a single question in a poll.
What I don't understand how to do is create a reference from one document to an embedded document in another document. For example:
var AnswerSchema = new Schema({
answer: { type: String, required: true },
time: { type: Date }
})
var AnswerHistorySchema = new Schema({
user: { type: Schema.ObjectId, ref: 'User' },
// I know this is wrong, but...
question: { type: Schema.ObjectId, ref: 'Question' },
answers: [AnswerSchema]
})
What am I missing here?
Do I need to reference the Poll instead, and keep track of which question the AnswerHistory applies to within the Poll?
Or does this mean I shouldnt be embedding questions within the poll documents?
Something else I'm not thinking of?
Edit: Here is a more concise way of looking at the problem:
var C = new Schema({...});
var B = new Schema({c: [C]});
var A = new Schema({c: { type: ObjectId, ref: 'B.c' });
Instead of having a history schema I'd rather to have 'versions' of the poll tracking the user and the answers.
every time that a user do a new poll you create a PollByUser object.
let's say:
var PollByUserSchema = new Schema({
user: { type: Schema.ObjectId, ref: 'User' },
poll:{ type: Schema.ObjectId, ref: 'Poll' },
taken:{
type:Date,
default:Date.now
}
});
module.exports = mongoose.model('PollByUser', PollByUserSchema);
var AnswerSchema = new Schema({
answer: { type: String, required: true },
time: { type: Date },
question: { type: Schema.ObjectId, ref: 'Question' },
pollByUser: { type: Schema.ObjectId, ref: 'PollByUser' },
})
EDIT:
var PollSchema = new Schema({
name: { type: String, required: true },
questions: [{ type: Schema.ObjectId, ref: 'Question' }]
})

Resources