Issue For Unique field? - node.js

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.

Related

Error in getting referenced objects in admin-bro Nodejs (There are no resources with given id)

So the error I am getting is There are no resources with given id: "workshop.timelines"\nThis is the list of all registered resources you can use.
This is the resource I am trying to visualize in adminbro
const LearnerSchema = new mongoose.Schema(
{
workshops: [
{
workshop: {
workshop_id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'workshop',
},
code: {
type: String,
},
timeline: {
type: mongoose.Schema.Types.ObjectId,
ref: 'workshop.timelines',
},
},
],
{ timestamps: true }
);
This is the workshop model:
const WorkshopSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
},
description: {
type: String,
},
timelines: [
{
group: {
type: Number,
},
city: {
type: mongoose.Schema.Types.ObjectId,
ref: 'city',
},
description: {
type: String,
},
venue: {
type: mongoose.Schema.Types.ObjectId,
ref: 'venue',
},
month: {
type: String,
},
start: {
type: Date,
},
end: {
type: Date,
},
registration_start: {
type: Date,
},
registration_end: {
type: Date,
},
registrations: {
type: Number,
default: 0,
},
registrations_cancelled: {
type: Number,
default: 0,
},
d_reg: {
type: Number,
default: 0,
},
classLink: {
type: String,
default: '',
},
status: {
type: String,
default: 'E',
},
resources: {
_id: false,
videoSessions: { type: Boolean, default: false },
},
},
],
status: {
type: String,
enum: ['NEW', 'F', 'DISABLED'], //f = FEATURED
default: 'NEW',
},
},
{ timestamps: true }
);
WorkshopSchema.index({ name: 'text', description: 'text' });
module.exports = Workshop = mongoose.model('workshop', WorkshopSchema);
Now, I have added both of these resources among others in my adminbro options, but when adminbro tries to fetch some records from the Collection, it fails with the error:
There are no resources with given id: "workshop.timelines"\nThis is the list of all registered resources you can use.
One more thing that might be affecting this issue is that in MongoDB the value of timelines in the workshop object is a mix of ObjectId and string, however I have tried converting all the object values to ObjectId but it still shows the same error.
Would really appreciate any help here.
had the same issue.
Basically, any ref model that appears in the models that are included in the resources array has to be included as well.
In your case, I will suggest to have a look at the ResourceOptions (https://adminbro.com/ResourceOptions.html) to see if you can included the nested property
comment out you're every (type: mongoose.Schema.Types.ObjectId,) to like this ↓↓ or you can delete it as well.
// type: mongoose.Schema.Types.ObjectId,
and it will work fine.
This is not working because by default, Mongoose adds an _id property to your schemas and you are explicitly defining it so need to explicitly insert it while creating but in AdminBro Dashboard you do not have that kind of option to add _id while creating any new Object. So, for that reason comment every _id generating field.

How to populate sub document of another model in mongoose?

I have two mongodb model as following.
const CompanySchema = new Schema(
{
sections: [{
name: { type: String },
budgets: [{ // indicates from CalcSchema
index: { type: Number },
title: { type: String },
values: [Number],
sum: { type: Number, default: 0 },
}],
}]
},
{ timestamps: true }
);
const CalcSchema = new Schema({
budget: {
type: Schema.Types.ObjectId, // I want to populate this field. this indicates budget document in Company model
ref: "Company.sections.budgets" //it's possible in mongoose?
},
expense: {
type: Number,
default: 0
}
});
budget field indicate one of budgets field in CompanySchema.
So I want to populate when get Calc data.
But I don't how to populate embedded document.
I tried set ref value to ref: "Company.sections.budgets". but it's not working.
Please anyone help.
Finally, I found answer myself.
There is useful plugin for it.
https://github.com/QuantumGlitch/mongoose-sub-references-populate#readme
And I learned that my schema structure was wrong. It's anti-pattern in mongodb.

MongoDB Aggregation based on corresponding array index matches for a chatting application

I want to implement an aspect of chatting application, i.e number of unseen / new messages for a particular chat.
Here's my chat Schema :
var chatSchema = new Schema({
name: { type: String, default: "friend_chat" },
chat_type: { type: String, default: "group" },
lastMessage: {
type: Schema.Types.ObjectId,
ref: 'Message',
default: ObjectId("000000000000000000000000")
},
participants: [{
_id: { type: Schema.Types.ObjectId, ref: 'Member' },
//used to keep track of new messages/messages count
lastMessageId: { type: String, default: "000000000000000000000000" },
//status can be admin,blocked,member
status: { type: String, default: "member" }
}],
isDeleted: { type: Boolean, default: false }
})
Here's my Message Schema :
var messageSchema = new Schema({
senderId: { type: Schema.Types.ObjectId, ref: 'Member' },
type: String,
content: String,
timeCreated: { type: Date, default: Date.now() },
chatId: { type: Schema.Types.ObjectId, ref: 'Chat' },
isRead: { type: Boolean, default: false },
isDeleted: { type: Boolean, default: false }
})
So the lastMessageId key in the participants arrays basically informs of the Id of the last Message the participant has seen. Therefore, to quickly retrieve the number of unseen Messages for a "single" chat window,how can I do this:
Message.aggregate([{$match:{chatId:INPUT_CHAT_ID,
senderId:PARTICIPANT'S_ID/req.session.userId,_id:
{$gt:participants.index.lastMessageId}}}])
For the above what should be the approach for getting the index.
Currently I have just implemented a linear search at frontend which gives me the lastMessageId as a parameter in the request to get around the problem but I want to know what should be the approach here.
Also suppose by linear search at the frontend,I am able to get the index,since frontend also has the copy of chat document(mongodb document) for displaying. Now I want to query the same thing but for multiple chats. Of course using Message.aggregate for each chatId is inefficient so what is the recommended way here.Currently from the front end I receive a JSONObject "chats" of this form:
`{ids:CHAT_IDs_array,last_Message_Ids :LAST_MESSAGE_IDS_array} `
in order meaning that the first index of CHAT_IDs array corresponds to first index of LAST_MESSAGE_IDS array
My attempted,incomplete,appraoch for this problem is as below :
`Message.aggregate([{chatId:{$in:chats.id},senderId:req.session.userId, _id:{$gt : ????}}])`
How to possibly make chats.id array index correspond with chats.last_Message_Ids index.
Also I would be appreciative if the answer doesn't impose any changes to the "Schema". Thanks

Find all the documents that has same subdocuments mongoose

I have postSchema which references the tagsSchema.
var tagsSchem = new Schema({
name: {
type: String,
required: true
}
}, {
timestamps: true
});
// create a schema
var postsSchema = new Schema({
title: {
type: String,
required: true,
unique: true
},
mainImage: {
type: String
},
category: {
type: String,
required: true
},
body: {
type: String,
required: true
},
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
tags: [tagsSchem]
}, {
timestamps: true
});
One post can contain any no. of tags. So if a post has 3 tags then I want to get all the posts with those 3 tags without querying it multiple times. Is it possible?
When you perform find, you can use the $in option to find values that are in your array. For example:
posts.find({tags:{$in:{["tag1","tag2","tag3"]}}, function(err,data) {
... //Your code here
}
This will take all the posts that contains one of the three tags. It's important you have to pass an array in the $in option. This should work.

mongoose - findOneAndUpdate with $set flag

Consider this command:
WorkPlan.findOneAndUpdate({ _id: req.params.id }, updateObj, function(err) {
...
})
versus this:
WorkPlan.findOneAndUpdate({ _id: req.params.id }, { '$set': updateObj }, function(err) {
...
})
While developing my project, I was surprised to find out that the result of the first command is the same as the result of the second command: the updateObj is merged into the existing record in the database, even in the first case when it is supposed to replace it. Is this a bug in mongoose/mongodb or am I doing something wrong? how can I replace an object on update instead of merging it? I'm using mongoose 4.0.7.
Thanks.
==========
Update:
This is the actual WorkPlan schema definition:
workPlanSchema = mongoose.Schema({
planId: { type: String, required: true },
projectName: { type: String, required: true },
projectNumber: { type: String, required: false },
projectManagerName: { type: String, required: true },
clientPhoneNumber: { type: String, required: false },
clientEmail: { type: String, required: true },
projectEndShowDate: { type: Date, required: true },
segmentationsToDisplay: { type: [String], required: false },
areas: [
{
fatherArea: { type: mongoose.Schema.ObjectId, ref: 'Area' },
childAreas: [{ childId : { type: mongoose.Schema.ObjectId, ref: 'Area' }, status: { type: String, default: 'none' } }]
}
],
logoPositions: [
{
lat: { type: Number, required: true },
lng: { type: Number, required: true }
}
],
logoPath: { type: String, required: false },
}, { collection: 'workPlans' });
WorkPlan = mongoose.model('WorkPlan', workPlanSchema);
And this is an example of updateObj:
var updateObj = {
projectManagerName: projectManagerName,
clientEmail: clientEmail,
clientPhoneNumber: clientPhoneNumber,
segmentationsToDisplay: segmentationsToDisplay ? segmentationsToDisplay.split(',') : []
}
Therefore, when I'm NOT using the $set flag, I would expect the field projectNumber, for example, not to exist in the new record, yet I see it is still there.
Mongoose update treats all top level keys as $set operations (this is made more clear in the older docs: Mongoose 2.7.x update docs).
In order to get the behavior you want, you need to set the overwrite option to true:
WorkPlan.findOneAndUpdate({ _id: req.params.id }, updateObj, { overwrite: true }, function(err) {
...
})
See Mongoose Update documentation
In addition to the answer above:
[options.overwrite=false] «Boolean» By default, if you don't include
any update operators in doc, Mongoose will wrap doc in $set for you.
This prevents you from accidentally overwriting the document. This
option tells Mongoose to skip adding $set.
Link to docs: https://mongoosejs.com/docs/api.html#model_Model.update
This is works for me $set in Mongoose 5.10.1,
WorkPlan.where({ _id: req.params.id }).updateOne(updateObj);
Note:if you have inner object then give exact path of each key in updateObj
example:
"Document.data.age" = 19
ref: https://mongoosejs.com/docs/api.html#query_Query-set

Resources