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.
Related
Using the model.find method I can find documents that match all properties defined within my schema except when a property has a type of mongoose.Schema.ObjectId. In my case, references to the owner of the document. I've tried all sorts of ways to get documents by the owner _id but nothing is working. Anybody know the proper way to do this ?
--EDIT--
Just in case anybody runs into the same issue, I got it working using the following query.
Query:
const users_cars = await Cars.find( { owner: user_id } );
Schema:
const Schema = new mongoose.Schema({
type: Object,
owner: {
type: mongoose.Schema.ObjectId,
ref: 'User',
required: [ true, 'car must belong to an owner' ]
},
name: String
});
My database contains two different collections I have "groups" and I have "users". Each group has a field "participants" which is an array that contains either users or guests. Guests unlike users are stored in the group (since they're bound to the specific group).
I use the "participant" schema as an abstraction object between users/guests and the group, this way I can give different users different privileges.
Now to my problem. What I want is the "participant" schema to work for both users and guests which it would if guests would have been its own collection. However, in this case guests belong to the group object and I'm therefore not sure how I'm supposed to reference it. I've tried enum: ["user", "guests"] and enum: ["user", "meetings.guests"] but without any result. I only get the following error:
MissingSchemaError: Schema hasn't been registered for model "guests".. This tells me that I obviously haven't understood how to reference/link subdocuments in the same collection.
Note that I don't want guests to be their own collection
Maybe I can somehow move the "guest" object to "participants.user" but then I would somehow have to tell mongo that it's not an ObjectId anymore but an object?
Group.model.ts
export const ParticipantSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
required: true,
refPath: "participants.userModel"
},
userModel: {
type: String,
required: true,
enum: ["user", "guests"] // How am I supposed to connect the guests as reference? The guests don't have their own collection, they are stored inside the group
},
privilege: {
type: Number,
required: true
}
})
export const GroupSchema = new Schema({
title: {
type: String,
required: true
},
description: {
type: String
},
participants: [ParticipantSchema],
guests: [GuestSchema]
}, {
timestamps: true
})
export default database.model("group", GroupSchema)
User.model.ts
export const UserSchema = new Schema({
username: {
type: String,
required: true
},
password: {
type: String,
required: true,
}
}, {
timestamps: true
})
export default database.model("user", UserSchema)
I have a User schema created with Mongoose that holds a customer array, and inside that customer array there is another fleet array. I have figured out how to push to the customer array within the User schema, however I can not figure out how to loop through the customers, find the customer via id or name, and then push data into the fleet array.
Here is my User schema:
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
username: {
type: String,
default: ''
},
password: {
type: String,
default: '',
},
registerDate: {
type: Date,
default: Date.now()
},
customer: [{
name: {
type: String,
default: '',
},
email: {
type: String,
default: 'No email addresses found',
},
fleet: [{
unitType: {
type: String,
default: 'No type selected',
},
unitNumber: {
type: String,
default: 'No unit number provided',
},
vinNumber: {
type: String,
default: 'No vin number provided'
},
}]
}]
});
module.exports = mongoose.model('User', UserSchema);
I was able to figure out how to push a new customer into the customer array no problem. My problem is I do not get how I can loop through the customer array, and once I find the customer that I need, push data into the fleet array. I am really just stumped on how to word my Google search! Hopefully this is detailed enough, and please let me know if you need to see any other code.
You need to use positional '$' operation. Read here
UserSchema.update(
{'customer.email':'xyz#email.com'},
{
$push:{
'customer.$.fleet':<fleet object>
}
},function(err,result){
})
--- OR ---
UserSchema.update(
{'customer.email':'xyz#email.com'},
{
$set:{
'customer.$.fleet':[fleet array]
}
},function(err,result){
})
Hope this helps.
I have been trying to find a way to enforce the default value of a schema so that the default value is being used upon insert regardless of any input parameter. In other words a property of a schema should always have the default value and if any other parameter is being passed on insert/write that passed parameter would be ignored.
As an example, please see my dummy schema below. The property I want to enforce is MySchema.created, which is supposed to store the timestamp of the moment document gets created.
var mongoose = require("mongoose");
var MySchema = new mongoose.Schema({
sendStatus: {
type: String,
enum: ["notsent", "sent", "failed"],
default: "notsent"
},
created: {
type: Date,
default: Date.now
},
creator: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true
}
});
I did not find an answer in Mongoose documentation (http://mongoosejs.com/docs/defaults.html) even though it do mention setDefaultsOnInsert, which sounds somewhat close. Altough I would like to do all the schema validation and enforcements on schema level to avoid development mistakes and copy-paste code. Also I don't see how I could use setDefaultsOnInsert for this timestamp, because I want to keep it also constant and not update it upon document update.
Is this possible to achieve? Having a reliable creation date on a document must be a very common use case, but somehow I fail to find a satisfying answer in the internet. Thanks!
You can simply add Mongoose timestamps to the end of your schema and it will timestamp your new/updated document
var MySchema = new mongoose.Schema({
sendStatus: {
type: String,
enum: ["notsent", "sent", "failed"],
default: "notsent"
},
creator: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true
}
},{
timestamps:
{
createdAt: 'created_at',
updatedAt: 'updated_at' //leave this out if of no interest
}
});
I have these mongoose schemas:
var ItemSchema = new Schema({
"pieces": Number,
"item": { type: Schema.Types.ObjectId, ref: 'Items' }
});
var cartSchema= new Schema({
"items": [ItemSchema]
});
but when I want to push a new item in items, mongoose add an _id field(on the new item) but I don't understand why.
if you want to add item without _id field then you should add { _id: false } in ItemSchema.
var ItemSchema = new Schema({
"pieces": Number,
"item": { type: Schema.Types.ObjectId, ref: 'Items' }
}, { _id: false });
Mongoose assigns each of your schemas an _id field by default if one is not passed into the Schema constructor. The type assigned is an ObjectId to coincide with MongoDB's default behavior. If you don't want an _id added to your schema at all, you may disable it using this option.
You can only use this option on sub-documents. Mongoose can't save a document without knowing its id, so you will get an error if you try to save a document without an _id.
Link: http://mongoosejs.com/docs/guide.html#_id