Resolving the OverwriteModelError in mongoose - node.js

Hi I wrote a Lambda function using nodejs to retrieve the data's from mongodb and it works fine. Later I use the API to produce link and to view the output in that link. Now the output is showed in console but in that API it showing OverwriteModel Error.I attached my code and output in API. What shall I do now ?
const mongoose = require('mongoose')
const models=()=>{
mongoose.connect('---',{useNewUrlParser:true,useCreateIndex:true,useUnifiedTopology:true})
const wavicle = mongoose.model('Datasetlist',{Dataset:[{id:Number,dataset:String,parameter:
{name:String}]}]})
const me = wavicle.find({})
return me
}
const main = async(event)=>{
console.log('EVENT:',event)
return models()
}
exports.handler = main
CONSOLE OUTPUT:
[
{
"_id": "5f05714c96db3e0007ae3595",
"Dataset": [
{
"parameter": [
{
"_id": "5f05714c96db3e0007ae3597",
"name": "StoreName"
},
{
"_id": "5f05714c96db3e0007ae3598",
"name": "Dates"
},
{
"_id": "5f05714c96db3e0007ae3599",
"name": "TransDesc"
},
{
"_id": "5f05714c96db3e0007ae359a",
"name": "Amount"
},
{
"_id": "5f05714c96db3e0007ae359b",
"name": "credit"
},
{
"_id": "5f05714c96db3e0007ae359c",
"name": "total"
}
],
"_id": "5f05714c96db3e0007ae3596",
"id": 1,
"dataset": "Daily Food Report"
}
],
"__v": 0
}
]
API OUTPUT:
{
"errorType": "OverwriteModelError",
"errorMessage": "Cannot overwrite `Datasetlist` model once compiled.",
"trace": [
"OverwriteModelError: Cannot overwrite `Datasetlist` model once compiled.",
" at Mongoose.model (/var/task/node_modules/mongoose/lib/index.js:524:13)",
" at models (/var/task/index.js:7:26)",
" at Runtime.main [as handler] (/var/task/index.js:18:12)",
" at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
]
}

"errorType": "OverwriteModelError" signifies that you are over writting Datasetlist model
which already exist in your database under different Schema or same name like DataSetlist or DATASETLIST or dataSetlist .
First delete previous model.
Then run your code ,this time it will create new model without any error

I'm defining the mongodb connection and creating mongoose model inside the models function so every time it creating the mongoose model with same name and same schema repeatedly and overwriting so it's shows the error "overwritemodelerror". Now I had kept the mongoose model and mongodb connection part outside the models function
const mongoose = require('mongoose')
mongoose.connect('mongodb+srv://Sethu16:Sethu16##samplecluster.xtrb0.mongodb.net/Wavicle?retryWrites=true&w=majority',{useNewUrlParser:true,useCreateIndex:true,useUnifiedTopology:true})
const Wavicle = mongoose.model('Datasetlist',{Dataset:[{id:Number,dataset:String,parameter:[{name:String}]}]})
const models=()=>{
const me = Wavicle.find({})
return me
}
const main = async(event)=>{
console.log('EVENT:',event)
return models()
}
exports.handler = main
CONSOLE OUTPUT:
[
{
"_id": "5f05714c96db3e0007ae3595",
"Dataset": [
{
"parameter": [
{
"_id": "5f05714c96db3e0007ae3597",
"name": "StoreName"
},
{
"_id": "5f05714c96db3e0007ae3598",
"name": "Dates"
},
{
"_id": "5f05714c96db3e0007ae3599",
"name": "TransDesc"
},
{
"_id": "5f05714c96db3e0007ae359a",
"name": "Amount"
},
{
"_id": "5f05714c96db3e0007ae359b",
"name": "credit"
},
{
"_id": "5f05714c96db3e0007ae359c",
"name": "total"
}
],
"_id": "5f05714c96db3e0007ae3596",
"id": 1,
"dataset": "Daily Food Report"
}
],
"__v": 0
}
]
API OUTPUT:
[
{
"_id": "5f05714c96db3e0007ae3595",
"Dataset": [
{
"parameter": [
{
"_id": "5f05714c96db3e0007ae3597",
"name": "StoreName"
},
{
"_id": "5f05714c96db3e0007ae3598",
"name": "Dates"
},
{
"_id": "5f05714c96db3e0007ae3599",
"name": "TransDesc"
},
{
"_id": "5f05714c96db3e0007ae359a",
"name": "Amount"
},
{
"_id": "5f05714c96db3e0007ae359b",
"name": "credit"
},
{
"_id": "5f05714c96db3e0007ae359c",
"name": "total"
}
],
"_id": "5f05714c96db3e0007ae3596",
"id": 1,
"dataset": "Daily Food Report"
}
],
"__v": 0
}
]

Related

How to get mongoose schema result properly with missing field in JSON

I am new to Node.js and mongoose. I have tried a lot of things but not able to get the result I want.
Can someone help who knows how, who has faced this problem before or knows the solution of that problem?
Below is my database screen where 3 records are insured like below.
I have written this code and it returns the result shown below:
router.get("/categoryFields", async (request, response) => {
const categories = await categoryModel.find({}).select("parentId title slug");
try {
response.send(categories);
} catch (error) {
response.status(500).send(error);
}
});
JSON result =>
[
{
"_id": "61779e5c1e4ed11e96301ccd",
"title": "Clothing",
"slug": "hello"
},
{
"_id": "61779e8d1e4ed11e96301ccf",
"parentId": "61779e5c1e4ed11e96301ccd",
"title": "Shoe",
"slug": ""
},
{
"_id": "6177c1cd6d3e170ae58c89c3",
"title": "Electric",
"slug": ""
}
]
But I need to get a result like this - I want parentID in every object:
[
{
"_id": "61779e5c1e4ed11e96301ccd",
"parentId": "",
"title": "Clothing",
"slug": "hello"
},
{
"_id": "61779e8d1e4ed11e96301ccf",
"parentId": "61779e5c1e4ed11e96301ccd",
"title": "Shoe",
"slug": ""
},
{
"_id": "6177c1cd6d3e170ae58c89c3",
"parentId": "",
"title": "Electric",
"slug": ""
}
]
Please can anyone help me how to do this in mongoose?
db.collection.find({},
{
"parentId": {
$cond: {
if: "$parentId",
then: "$parentId",
else: ""
}
},
"title": 1,
"slug": 1
})
Test Here

How to find a specific _id and update it from an array of objects?

I want to access a specific document which resides inside like:-
[
{
"_id": "60ebf0704c56861e10a7c69b",
"id": "100",
"name": "Shubham Sharma",
"allTasks": [
{
"_id": "60ebf08d4c56861e10a7c6a3",
"taskName": "Training",
"date": "2021-07-13",
"time": "16:04",
"taskColor": "#ffffcc"
},
{
"_id": "60ebf09e4c56861e10a7c6a7",
"taskName": "Project",
"date": "2021-07-15",
"time": "15:06",
"taskColor": "#B2D8B2"
},
{
"_id": "60ebf0be4c56861e10a7c6ab",
"taskName": "Leave",
"date": "2021-07-15",
"time": "",
"taskColor": "pink"
},
{
"_id": "60ebf0d94c56861e10a7c6af",
"taskName": "Project XYZ to be completed",
"date": "2021-07-16",
"time": "16:05",
"taskColor": "#FFE4B2"
}
],
"__v": 4
},
{
"_id": "60ebf07b4c56861e10a7c69f",
"id": "200",
"name": "Karan Srivastava",
"allTasks": [
{
"_id": "60ebf0fb4c56861e10a7c6b3",
"taskName": "Training",
"date": "2021-07-14",
"time": "17:06",
"taskColor": "#B2D8B2"
}
],
"__v": 1
}
]
I want to access a document in allTasks array by using _id of that particular allTasks document and then update the fields in it which are taskName,date,time,taskColor. How to findOneAndUpdate a specific document in allTasks array.
Suppose i want to update
"_id": "60ebf0be4c56861e10a7c6ab",
"taskName": "Leave",
"date": "2021-07-15",
"time": "",
"taskColor": "pink"
TO
"_id": "60ebf0be4c56861e10a7c6ab",
"taskName": "Some Task",
"date": "2021-07-16",
"time": "17:00",
"taskColor": "green"
How to do this?
this should work according to
https://mongoosejs.com/docs/subdocs.html
const mongoose = require('mongoose')
const Parent = mongoose.model('Parent')
const { ObjectId } = mongoose.Types
const parent = await Parent.findOne({ _id: new ObjectId('60ebf0704c56861e10a7c69b') })
const child = parent.allTasks.id(new ObjectId('60ebf0be4c56861e10a7c6ab')) // this is an in memory search and doesnt hit the database, so no need for 'await'
child.set({
taskName: 'Some Task',
date: '2021-07-16',
time: '17:00',
taskColor: 'green'
})
await parent.save()

Mongoose: Update of array inside another nested array element not working as expected

Here is my mongo schema:
{
"_id": ObjectId("5f8af2fc5f23667adf3bbaf2"),
"score": 2.5,
"questions": [{
"_id": ObjectId("5f8af30d5f23667adf3bbaf5"),
"desc": "some text",
},
{
"_id": ObjectId("5f8af3115f23667adf3bbaf8"),
"desc": "some text",
"options": [{
"_id": ObjectId("5f8af3115f23667adf3bbaf9"),
"name": "some name",
"desc": "description 1"
},
{
"_id": ObjectId("5f8af3115f23667adf3bbafa"),
"name": "some name",
"desc": "description 2"
}
]
}
]
}
I've to update the name and desc of the option having id as 5f8af3115f23667adf3bbaf9 which is in the one of the array elements of the question attribute having id as 5f8af30d5f23667adf3bbaf5 which is again part of the data having id as 5f8af2fc5f23667adf3bbaf2
Tried the following query which is getting executed successfully but not updating the option:
Model.findOneAndUpdate({
_id : ObjectId("5f8af2fc5f23667adf3bbaf2"),
"questions._id": ObjectId("5f8af30d5f23667adf3bbaf5"),
"questions.options._id": ObjectId("5f8af3115f23667adf3bbaf9"),
}, {
$set: {
"questions.$[q].options.$[o].order": data.order,
"questions.$[q].options.$[o].definition": data.definition,
"questions.$[q].options.$[o].type": data.type,
},
},
{
arrayFilters: [{ "q._id": ObjectId(qid) }, { "o._id": ObjectId(oid) }]
})
Is tihs possible to do in a single mongoose findOneAndUpdate method?
Your query is correct, I have just hardcoded object id values in array filter and it is updating the documents. I have updated name and desc as u said. Do try this out. One more thing in mongoose u have to specify the object id as "mongoose.Types.ObjectId".
Therefore in your case it would be like "q._id": mongoose.Types.ObjectId("5f8af3115f23667adf3bbaf8").
And one more thing is that you are using findAndUpdate, try using update only depending on your mongoose version
Here is mongoplayground:
https://mongoplayground.net/p/TP5iCTAC5R_
Query:
db.collection.update({
_id: ObjectId("5f8af2fc5f23667adf3bbaf2"),
"questions._id": ObjectId("5f8af3115f23667adf3bbaf8"),
"questions.options._id": ObjectId("5f8af3115f23667adf3bbaf9")
},
{
$set: {
"questions.$[q].options.$[o].name": "anotherName",
"questions.$[q].options.$[o].desc": "anotherDesc"
}
},
{
arrayFilters: [
{
"q._id": ObjectId("5f8af3115f23667adf3bbaf8")
},
{
"o._id": ObjectId("5f8af3115f23667adf3bbaf9")
}
]
})
Output :
[
{
"_id": ObjectId("5f8af2fc5f23667adf3bbaf2"),
"questions": [
{
"_id": ObjectId("5f8af30d5f23667adf3bbaf5"),
"desc": "some text"
},
{
"_id": ObjectId("5f8af3115f23667adf3bbaf8"),
"desc": "some text",
"options": [
{
"_id": ObjectId("5f8af3115f23667adf3bbaf9"),
"desc": "anotherDesc",
"name": "anotherName"
},
{
"_id": ObjectId("5f8af3115f23667adf3bbafa"),
"desc": "description 2",
"name": "some name"
}
]
}
],
"score": 2.5
}
]

How to query nested object in mongodb

I'm new to mongodb and I've been trying to query this doc for awhile now.
Im trying to query all the rooms that have a room name of 100.
json
{
"count": 3,
"reviews": [
{
"_id": "5f9d42a0a8e71e004643f584",
"user": {
"_id": "5f7308cde0a4a7a66bc3d184",
"name": "Guest"
},
"room": {
"_id": "5f98f9321fd5bb0045b3d886",
"name": "100",
},
"rating": 4,
},
{
"_id": "5f9d431ea8e71e004643f585",
"user": {
"_id": "5f7308cde0a4a7a66bc3d184",
"name": "Guest",
},
"room": {
"_id": "5f98f9321fd5bb0045b3d886",
"name": "100",
},
"rating": 5,
},
{
"_id": "5f9e74fea6c06a0046d3cae2",
"user": {
"_id": "5f7308cde0a4a7a66bc3d184",
"name": "Guest",
},
"room": {
"_id": "5f98fa8b1fd5bb0045b3d88a",
"name": "300",
},
"rating": 5,
}
]}
what I've tried
1. find({},{"reviews.room.name": {$eq: "100"}}) // getting a projection error
2. find({"reviews.room.name": "100"}) // getting null
Any help to the right direction would be greatly appreciated.
Check out the docs about how to use find:
https://docs.mongodb.com/manual/reference/method/db.collection.find/
and try this
db.reviews.find({
"room.name": "100"
})
Here is the playground with your example: https://mongoplayground.net/p/dPfH5fSOePq
did u try this ? const response = await Room.find({name: "100"})

Create Mongoose Find and populate from multiple tables with property set

I'll be grateful for help with Mongoose. I have 3 tables: (Users)Table of users, (Animals)table of animals and table AnimalComments. So (AnimalComments)table reference users and animals.
const schemaComment = new mongoose.Schema({
userRef: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
animalRef: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Animal'
},
content: {
type: String
}
});
const schemaAnimal = new mongoose.Schema({
name: {
type: String
},
isCommentedByMe: {
type : Boolean,
default: false
},
commentCount: {
type : Number,
default: 0
}
});
What I want: I have animals. Users can add comment to animal. When user comment animal his comment is added to table AnimalComments where is stored userRef (userId), animalRef (animalId) and user comment text. Then in request response I want return all animals from table Animals but I need update property commentCount and isCommentedByMe based on value from table AnimalComments.
Response from table Animals:
{
"animals": [
{
"isCommentedByMe": false,
"commentCount": 0,
"name": "Jessica",
"userRef": {
"id": "5dc9bdf3dd5cae00177e184d"
},
"id": "5dcedd48368e9800176f2ef3"
}
]
}
Response from table Users:
{
"users": [
{
"name": "Jony Cash",
"id": "5dc9bdf3dd5cae00177e184d"
}
]
}
Response from table AnimalComments:
{
"comments": [
{
"userRef": "5dc9bdf3dd5cae00177e184d",
"animalRef": "5dcedd48368e9800176f2ef3",
"content": "Sample text"
}
]
}
I want result for exmaple:
{
"animals": [
{
"isCommentedByMe": true,
"commentCount": 4,
"name": "Jessica",
"userRef": {
"id": "5dc9bdf3dd5cae00177e184d"
},
"id": "5dcedd48368e9800176f2ef3"
}
]
}
You don't need to keep isCommentedByMe and commentCount fields in animal schema.
And you need to be able access comments from your animals. But in animal schema there is no field to make that connection. So we need to use virtual population.
So your animal schema must be like this:
const schemaAnimal = new mongoose.Schema(
{
name: {
type: String
}
},
{
toJSON: { virtuals: true },
toObject: { virtuals: true }
}
);
// Virtual populate
schemaAnimal.virtual("comments", {
ref: "Comment", //must be changed to the name you used for Comment model.
foreignField: "animalRef",
localField: "_id"
});
Now, we can use the following code to populate the comments.
router.get("/animals", async (req, res) => {
const animals = await Animal.find({}).populate("comments");
res.send(animals);
});
This will give you a result like this:
[
{
"_id": "5dd66c73069f88614c12b394",
"name": "Animal 1",
"__v": 0,
"comments": [
{
"_id": "5dd66cfd069f88614c12b39a",
"userRef": "5dd66b54c5195127ec5a1b82",
"animalRef": "5dd66c73069f88614c12b394",
"content": "User 1 - Animal 1",
"__v": 0
},
{
"_id": "5dd66d30069f88614c12b39d",
"userRef": "5dd66b71c5195127ec5a1b83",
"animalRef": "5dd66c73069f88614c12b394",
"content": "User 2 - Animal 1",
"__v": 0
}
],
"id": "5dd66c73069f88614c12b394"
},
{
"_id": "5dd66c7d069f88614c12b395",
"name": "Animal 2",
"__v": 0,
"comments": [
{
"_id": "5dd66d09069f88614c12b39b",
"userRef": "5dd66b54c5195127ec5a1b82",
"animalRef": "5dd66c7d069f88614c12b395",
"content": "User 1 - Animal 2",
"__v": 0
}
],
"id": "5dd66c7d069f88614c12b395"
},
{
"_id": "5dd66c88069f88614c12b396",
"name": "Animal 3",
"__v": 0,
"comments": [
{
"_id": "5dd66d46069f88614c12b39e",
"userRef": "5dd66b71c5195127ec5a1b83",
"animalRef": "5dd66c88069f88614c12b396",
"content": "User 2 - Animal 3",
"__v": 0
}
],
"id": "5dd66c88069f88614c12b396"
}
]
To convert this result to what you wanted, we can use map like this:
Please note that, you need to set loggedInUserId variable to logged in user's id.
router.get("/animals", async (req, res) => {
const loggedInUserId = "5dd66b54c5195127ec5a1b82";
const animals = await Animal.find({}).populate("comments");
const result = animals.map(animal => {
return {
id: animal._id,
name: animal.name,
isCommentedByMe:
animal.comments.filter(c => c.userRef.toString() === loggedInUserId)
.length > 0,
commentCount: animal.comments.length
};
});
res.send(result);
});
The result will be like this:
[
{
"id": "5dd66c73069f88614c12b394",
"name": "Animal 1",
"isCommentedByMe": true,
"commentCount": 2
},
{
"id": "5dd66c7d069f88614c12b395",
"name": "Animal 2",
"isCommentedByMe": true,
"commentCount": 1
},
{
"id": "5dd66c88069f88614c12b396",
"name": "Animal 3",
"isCommentedByMe": false,
"commentCount": 1
}
]
And the answer for the question in the comments is: (how to reference User)
const animals = await Animal.find({}).populate({
path: "comments",
model: Comment,
populate: [
{
path: "userRef",
model: User
}
]
});
This will give you the userRef like this:
[
{
"_id": "5dd66c73069f88614c12b394",
"name": "Animal 1",
"__v": 0,
"comments": [
{
"_id": "5dd66cfd069f88614c12b39a",
"userRef": {
"_id": "5dd66b54c5195127ec5a1b82",
"name": "User 1",
"__v": 0
},
"animalRef": "5dd66c73069f88614c12b394",
"content": "User 1 - Animal 1",
"__v": 0
},
{
"_id": "5dd66d30069f88614c12b39d",
"userRef": {
"_id": "5dd66b71c5195127ec5a1b83",
"name": "User 2",
"__v": 0
},
"animalRef": "5dd66c73069f88614c12b394",
"content": "User 2 - Animal 1",
"__v": 0
}
],
"id": "5dd66c73069f88614c12b394"
},
{
"_id": "5dd66c7d069f88614c12b395",
"name": "Animal 2",
"__v": 0,
"comments": [
{
"_id": "5dd66d09069f88614c12b39b",
"userRef": {
"_id": "5dd66b54c5195127ec5a1b82",
"name": "User 1",
"__v": 0
},
"animalRef": "5dd66c7d069f88614c12b395",
"content": "User 1 - Animal 2",
"__v": 0
}
],
"id": "5dd66c7d069f88614c12b395"
},
{
"_id": "5dd66c88069f88614c12b396",
"name": "Animal 3",
"__v": 0,
"comments": [
{
"_id": "5dd66d46069f88614c12b39e",
"userRef": {
"_id": "5dd66b71c5195127ec5a1b83",
"name": "User 2",
"__v": 0
},
"animalRef": "5dd66c88069f88614c12b396",
"content": "User 2 - Animal 3",
"__v": 0
}
],
"id": "5dd66c88069f88614c12b396"
}
]

Resources