Nested Collection in MongoDB - node.js

const onboarderSchema = new Schema({
name: {
type: String,
required: [true, "name field is required"]
},
email: {
type: String
},
project: {
type: Object,
projectName: {
type: String,
required: [true]
},
projectDescription: {
type: String
},
manager: {
type: String,
required: [true]
},
mentor: {
type: String,
required: [true]
},
technologies: {
type: [Number],
required: [true]
}
}
});
This is a schema for my project which I am working on. The Project which is an object will have different projects added to it dynamically. So should I change the type of project to an array or something else? Cannot figure out what to do. Please suggest.

Make it array. Remember object is for a single information with fixed fields and values. on the other hand, array is to hold many information where you can put objects as many as you need dynamically. Then it will be called an array of objects. Keep the object fields same in the array to keep consistency and flexible query operation.

If you want to have multiple project inside your database the project field should be an array like
project:[{projectName:"p1"},
{projectName:"p2"},
{projectName:"p3"}]
or like this
project:["p1","p2","p3"]

Related

Mongoose aggregate and append

I have a Mongo DB (latest version) that I am accessing with Mongoose (v6.5.4)
The project is using a discriminator pattern to keep all documents in the same collection.
There are many instances where i need to join documents.
Set up:
// Models:
const UserSchema = new Schema<IUser>(
{
firstName: {
type: String,
required: true,
},
lastName: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
});
// There are other similar models to <Team>
const TeamSchema = new Schema<ITeam>(
{
name: {
type: String,
required: true,
},
userIds: {
type: [Schema.Types.ObjectId],
required: true,
ref: "User",
default: [],
},
});
Problem:
I can use populate to return collections of Teams and the userIds be an array of user objects.
Where I am stuck is querying getting an array of users with an added field of teams[].
I've been trying aggregate to no success, I can loop over the users collection and return a list of Teams but this feels wrong and expensive in terms of read units (production data base is on a pay as you go service)
As data models go there is not much going for it - but it is an existing solution
Can anyone advise?
I was being stupid. The from field in my look up was wrong.
Should have been 'teams' not 'Team' which is the model name.

Filter documents using multiple fields

I have a collection named Project. Below is the schema description for Project collection :
const projectSchema = new mongoose.Schema(
{
projectName: {
type: String,
trim: true
},
licenceType: {
type: String,
trim: true,
lowercase: true
},
location: {
type: String,
lowercase: true,
trim: true
},
description: {
type: String,
trim: true
},
projectType: {
type: String,
default: 'public'
},
status: {
type: String,
default: 'open'
},
budget: {
type: Number
},
duration: {
type: Number
},
},
{
timestamps: true
}
);
I want to fetch documents using these fields as filters. The fields are :
licenceType
location
date (timestamp is made true in schema for this purpose)
I can use these three fields in any combination to fetch documents. There is a possibility that no filter is applied at all in which case its a simple fetching of all the documents in the collection.
I know I can dynamically build query using if--else if--else but I wanted to know is there any other more efficient way of handling such queries rather than using if--else blocks. If there would have been five or more fields for filtering purpose, there would be so many combinations to check using if--else block.
Appreciate any kind of help!!Thank You.
So, I assume there's some external trigger which actually modifies the filter matrix (eg. a request from some UI). Mongoose allows you to specify filter up-front in a form of an object, take a look below:
const query = Project.find({
licenceType: 'sometype',
location: 'somelocation'
});
Clearly you can see this...
{
licenceType: 'sometype',
location: 'somelocation'
}
...is an object. So, I think you could re-build the filtering object each time filters change (create an empty object let myFilters = {} and extend it with your filters: myFilters['licenceType'] = 'sometype') and pass myFilters to find function.

MongoDB: How do you create an index on a field which is nested in two arrays?

I have a Mongo schema which essentially has two nested arrays, each of which contain objects. I would like to create an index on a field nested in that second level array. The schema looks as such:
const restaurantsSchema = new Schema({
restaurantName: { type: String, required: true },
dishes: [{
dishName: String,
price: Number,
description: String,
reviews: [{
reviewId: Number, **<<<< INDEX THIS FIELD**
userId: {
type: Schema.Types.ObjectId,
ref: 'users',
required: true,
},
photoUrl: String,
caption: String,
createdAt: Number,
updatedAt: Number,
rating: Number,
reviewText: String,
}],
}],
});
The idea is that I can use this index to find and update a user's reviews. Is this possible with Mongo's multikey indexing or is there another way to do this? Any help would be appreciated.
I believe if you change the schema to
reviewId: {
type: Number,
unique: true
}
mongodb automatically creates an index because each value should be unique. That really the only qualification for creating any index.
write back if it works!

Mongodb, mongoose, Schema structure. get a collection into a field of other collection

I have a schema "Questions" it has like a dozen of questions in it, I can add and delete those questions, I need this collection reflected in a field of other collection - "User" with one additional field (nested in options).
Question Schema:
var QuestionScema = new mongoose.Schema({
key: { type: String, required: true },
label: { type: String, required: true },
name: { type: String, required: true },
page: { type: String, required: true },
type: { type: String, required: true },
options: [{
key: {type: String, required: true},
value: {type: String, required: true}
}],
});
User Schema:
var UserSchema = new mongoose.Schema({
Name: { type: String, required: true },
Email: { type: String, required: true, unique: true },
Password: { type: String, required: true },
//this is where I need to reflect a Questions collection on each user,
//so that it will look something like this//
Questions: [{
key: {type: String, required: true},
//here can be all other fields from Questions collection, that is not a problem
options: [{
key: {type: String, reuired: true},
value: {type: String, reuired: true},
counter: {type: Number, default: 0} //this is the additional field
}]
}],
//
Notifications: [{
Title: { type: String },
Data: { type: String },
Created: { type: Date, default: Date.now }
}]
});
I can't figure out how to do that.
I have another collection of users, say User2 that will answer those questions from Questions collections and I need to keep track on Users schema (not User2, there I just save questions and answers) of how many times an option for that question is chosen.
A Questiuons entry can look like this:
{
key: Haveyouseenthismovie,
label: Have you seen this movie?,
name: Have you seen this movie?,
page: 1,
type: dropdown,
options: [{
key: yes,
value: yes
}, {
key: no,
value: no
}]
}
I want it to work like that (reflect a collection in field of each User) so I don't have to check if that question is in User collection if not add and if it is, is there an option that I need if it is than increment, if not than add that option (that user selected from options in that question in Questions schema) and increment. That looks like a bummer. So I figured that it will be better if that field will reflect a collection and I will just increment the option that I need on a question that I need.
Please help me figure that out, I don't have enough practise in mongo so I struggle with it sometimes :)
I don't think there is a way to reflect a collection in another document as the way you seem to wish it.
As I understand, the following options are available for you:
Embed the entire question document inside the User documents in User Collection.
Just maintain the '_id' of the question document in the User document in User Collection.
Please read on Data Modelling concepts & maintaining relationship between documents from Mongo DB Page https://docs.mongodb.com/manual/applications/data-models-relationships/

Issue For Unique field?

I am working to maintain unique field in Mongodb but its not workig .
Here My code :
var RepositorySchema = new mongoose.Schema({
folderName: { type: String, unique: true},
tag: String ,
ismainFolder: { type: Boolean },
innerFiles: [{ filename: String, isFolder: { type: Boolean }, parentfolderId: { type: Schema.ObjectId, ref: 'repository' }, filelocation: { type: String } }],
innerFolder: [{ foldername: String, ismainFolder: { type: Boolean }, parentfolderId: { type: Schema.ObjectId, ref: 'repository' } }],
});
module.exports = mongoose.model('repository', RepositorySchema);
FolderName is not maintaining Unique Values , please help me
Try to recreate all indexes on your collection. Run the following commands in your terminal:
> mongo
> use <your_dv>
> db.repository.reIndex()
The reIndex command drops all indexes on a collection and recreates them. This operation may be expensive for collections that have a large amount of data and/or a large number of indexes.

Resources