Mongoose typeError with custom Schema - javascript

I'm trying to use discountSchema as a type. But I'm getting this error:
throw new TypeError('Undefined type at `' + path +
^
TypeError: Undefined type at `discount`
but if I transform to type array:
discount: {
type: [discountSchema],
default:{}
}
it works.
How can I use complex type in mongoose as this?
Am I using this model in a wrong way? How can I model this object like this?
var discountSchema = new Schema({
type: {type: String,default:'' },
quantity: {type: Number,default:0 },
value: {type: Number,default:0 }
});
var objectEncomendaPropertiesSchema = {
recheios:{
type:[String],
default: [],
select: true
},
availableEncomenda: {
type: Boolean,
default:false
},
discount: {
type: discountSchema,
default:{}
}
};

You cant't set embedded documents stored as single property in mongoose, they are always stored in arrays.
The closest thing to this behaviour is setting your property to an ObjectId with a ref and using the populate method to fetch it.
Take a look here to see how this approach works.
Check out embedded documents docs.
There is an open issue on GitHub requesting the behaviour you want.

are you trying to create two Schemas then wire them up?
var discountSchema = new Schema({
type: {type: String,default:'' },
quantity: {type: Number,default:0 },
value: {type: Number,default:0 }
});
mongoose.model('Discount', discountSchema);
var objectEncomendaPropertiesSchema = new Schema({
recheios:{
type: String,
default: '',
select: true
},
availableEncomenda: {
type: Boolean,
default:false
},
discount: {
type: Schema.Types.ObjectId,
ref: 'Discount'
}
})
mongoose.model('objectEncomendaProperties', objectEncomendaPropertiesSchema);
I reference the discount in the second schema to reference to the first schema by the ObjectId
It will fetch the properties in the Discount model as a discount property in the second Schema.

Related

How to push element parent in Mongoose?

I want to push an nested element Mongoose.
Check the schema:
const Messages = new mongoose.Schema({
/*[user]*/
author: {
type: Schema.Types.ObjectId,
ref: 'Users'
},
/*[room]*/
room: {
type: Schema.Types.ObjectId,
ref: 'Rooms'
},
message_body: String,
message_status:{type: Boolean, default: false},
created_at: { type: Date, default: Date.now }
});
I want to create a Message with room and Author insert, how to use that?
Imagine you have an 'author' object and a 'room' object. These are going to be the parents. Your message object would be like this:
var newMessage = new Message({author: authore._id, room: room._id, message_body: messageBody ....});
newMessage.save()
.then(() => {
/*** do more things **/
});
Then you will be able to use 'populate' option to make Mongoose refilling author and room fields with the whole objects.

Cast to ObjectId failed for value error in Mongoose findOne

I've been struggling with a weird exception and still confused about it after an hour.
CastError: Cast to ObjectId failed for value "pedrammarandi#gmail.com"
at path "_id" for model "Account"
I'm trying to retrieve an Account via email address. Here is my query
export async function getPendingRecipients(user_id, email_address) {
const account = await Account
.find({email: email_address})
.exec();
return true;
}
This is my Schema object
const userGmailSchema = new Schema({
id: {
type: String,
unique: true
},
displayName: String,
image: Object,
accessToken: String,
user: {
type: Schema.Types.ObjectId,
ref: 'User'
},
refreshToken: {
type: String,
default: null
},
email: {
type: String,
unique: true
},
emails: [
{
type: Schema.Types.ObjectId,
ref: 'Emails'
}
]
});
I'm not sure, but I guess the problem is you wrote an id field.
In MongoDB, the "primary key" is _id field, which is an ObjectId object (actually it's a 12-byte-value), and in mongoose, id is a virtual getter of _id, easily said, id is an alias of _id.
(A little different is that, _id returns ObjectId, id returns String version of _id.)
By default, mongoose manage _id field automatically, so commonly we should not write anything about id in schema.
If your id is for something like primary key ID in SQL DB, just remove it from mongoose schema. If it's means something else in your app, try to add an option:
const userGmailSchema = new Schema({
// your schemas here
},
{
{ id: false } // disable the virtual getter
})
or rename it.
http://mongoosejs.com/docs/guide.html#id
Hope this helps.

Does order of schema matter in Node.JS?

Im about to make a huge schema for a form that I have just built... that being said does my schema order have to mimic the form order, or can it just have all the inputs in any order I put them in ?
Example below.
can it be like this?
// link to mongoose
var mongoose = require('mongoose');
// define the article schema
var mapSchema = new mongoose.Schema({
created: {
type: Date,
default: Date.now
},
dd1: {
type: String,
default: ''
},
dd2: {
type: String,
default: ''
},
com1: {
type: String,
default: ''
},
com2: {
type: String,
default: ''
}
});
// make it public
module.exports = mongoose.model('Map', mapSchema);
Or does it have to be like this?
// link to mongoose
var mongoose = require('mongoose');
// define the article schema
var mapSchema = new mongoose.Schema({
created: {
type: Date,
default: Date.now
},
dd1: {
type: String,
default: ''
},
com1: {
type: String,
default: ''
},
dd2: {
type: String,
default: ''
},
com2: {
type: String,
default: ''
}
});
// make it public
module.exports = mongoose.model('Map', mapSchema);
does my schema order have to mimic the form order, or can it just have all the inputs in any order I put them in?
mongoose.Schema accepts a JavaScript object as its parameter. So your question boils down to:
Are JavaScript objects aware of the order their keys were defined in?
The answer to that is: No, key order is not maintained in JavaScript objects. The JS spec explicitly states that objects are unordered key/value collections. (compare)
Therefore it follows that mongoose.Schema could not rely on key order even if it tied to, which means you are free to order the keys in any way you like.
We can also tackle the question from the other end:
Is it likely that a front-end change like form field order forces me to rewrite my database backend code?
And the answer to that is: No, that is pretty darn unlikely. We can dismiss that thought without even looking into any kind of spec, because it would not make any kind of sense.

Mongoose/MongoDb ,how to validate an array of Ids against another model

I have 2 moongose Schema:
var Schema2 = new Schema({
creator : { type: String, ref: 'User'},
schema_name : [{ type: String}],
});
var Schema1 = new Schema({
creator : { type: String, ref: 'User'},
schema_ref : [{ type: String, ref: 'Schema2' }],
});
Would like to know which is the best practice when I create a new Schema1 check that every element of array schema_ref, have the same creator.
Because schema1 elements are added by client form and so i have to check that the schema_ref elements are owned by same User that send the form
You can try with either validator function, or with a simple 'save' middleware:
Schema1.pre('save', function(next) {
let owner;
for (let entry in this.schema_ref) {
if (!owner) {
owner = entry;
} else {
if (entry !== owner) {
return next(new Error("owner mismatch");
}
}
}
});
Also, your schema might not work as you expect it to, it looks like you actually need:
schema_ref: [{
type: {type: String},
ref: "User"
}]
Additionally, take a look at id-validator plugin, or some similar to that - it will, in addition to your validation, also check that all ref-type properties like this actually exist in the other (Users) collection.

Applying getters on a "find" query in Mongoose?

Sorry if this has been asked before (I've searched, honestly).
Basically, I have a simple schema:
var ProductSchema = new Schema({
name: {type: String},
image: {type: String, get: getImageUrl},
stock: {type: Number},
price: {type: Number},
description: String
});
where
var getImageUrl = function(imgUrl) {
if (imgUrl.indexOf('http://') !== 0) {
return 'http://' + os.hostname() + (app.port ? app.port : '') + '/public/' + imgUrl;
} else {
return imgUrl;
}
};
The getter itself works, if I retrieve a specific item from the database, but not when I try to use Product.find() or other queries, the getter doesn't get apply, and I get the "raw" (unprocessed) property. I've tried using Product.find({}, [], {getters: true} to no avail. Am I missing something?
EDIT - using mongod version 1.8.5 and mongoose 2.5.10
Ran into this same issue today -- getters not being applied when using a find(). My workaround was to use a virtual instead and include it in the json results.
schema.virtual("APP_ID_URL").get(function() {
if (this.APP_ID > 0){
return "<a href='#'>" + this.APP_ID + "</a>";
}
else{
return "";
}
});
schema.set('toJSON', { virtuals: true });
The schema should be under definition of getter, if you define schema after getter function definition, you can reach it. It should work according to the specification: http://mongoosejs.com/docs/getters-setters.html
Update your schema to add config for populating Object and JSON
var ProductSchema = new Schema({
name: {type: String},
image: {type: String, get: getImageUrl},
stock: {type: Number},
price: {type: Number},
description: String
},
{
toObject : {getters: true},
toJSON : {getters: true}
});
Reference: https://github.com/Automattic/mongoose/issues/2152

Categories

Resources