Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
45
rated 0 times [  51] [ 6]  / answers: 1 / hits: 13944  / 3 Years ago, fri, october 1, 2021, 12:00:00

I am having issues with mongoose queries when I query by an ObjectId field. Passing mongoose.Types.ObjectId or string both throws errors. TypeScript only stops complaining when I cast the ObjectId to mongoose.Schema.Types.ObjectId, which then crashes at runtime since it's not a valid ObjectId.


interface DocumentWithTimestamp extends Document<ObjectId> {
createdAt: Date;
updatedAt: Date;
}

First of all, I noticed that Document defines _id as ObjectId | undefined, which already complicates everything.


I define my Schemas as follows:


export interface LanguageSchema extends DocumentWithTimestamp {
langCode: string;
locale: string;
}


interface LanguageModel extends Model<LanguageSchema> {
mapToLanguage(language: LeanDocument<LanguageSchema> | LanguageSchema): Language;
}

const languageSchema = new Schema<LanguageSchema, LanguageModel>(
{
langCode: { type: String, required: true, trim: true },
locale: { type: String, unique: true, required: true, trim: true },
},
{ collection: 'language', timestamps: true, versionKey: false },
);

languageSchema.statics.mapToLanguage = function (language: LeanDocument<LanguageSchema> | LanguageSchema): Language {
return {
id: language._id?.toString() || '', // why is _id conditional...?
langCode: language.langCode,
locale: language.locale,
};
};

export const LanguageModel = model<LanguageSchema, LanguageModel>('Language', languageSchema);

Now querying my LanguageModel by _id or any other ObjectId field throws type errors:


export async function findLanguagesByIds(languageIds: string[]) {
return LanguageModel.find({ _id: { $in: languageIds } }).lean();
}

Error:


Argument of type '{ _id: { $in: string[]; }; }' is not assignable to parameter of type 'Callback<LanguageSchema[]>'.
Object literal may only specify known properties, and '_id' does not exist in type 'Callback<LanguageSchema[]>'.

When I try to cast string[] to Schema.Types.ObjectId[] array, the error goes away but this cannot be the solution, since it crashes at runtime (Schema.Types.ObjectId is not a valid ObjectId).


const languages = await LanguageModel.find({
_id: { $in: languageIds.map((id) => new mongoose.Schema.Types.ObjectId(id)) },
}).lean();

If I cast to mongoose.Types.ObjectId(to a real ObjectId) it throws errors again...


Any help is appreciated!


More From » node.js

 Answers
2

I found the solution to my problem.


mongoose Document is defined as follows:


class Document<T = any, TQueryHelpers = any, DocType = any> {
constructor(doc?: any);

/** This documents _id. */
_id?: T;

// ...
}

I extended it using Document<ObjectId>. The ObjectId type however was the Schema type, e.g.


import { ObjectId } from "mongoose";

But it actually should have been the actual ObjectId Type of mongoose and not the Schema type!


FIX:


import { Types } from "mongoose"

interface DocumentWithTimestamp extends Document<Types.ObjectId> {
createdAt: Date;
updatedAt: Date;
}

[#806] Saturday, September 25, 2021, 3 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
brodyfrancisi

Total Points: 1
Total Questions: 102
Total Answers: 89

Location: Marshall Islands
Member since Mon, May 31, 2021
3 Years ago
brodyfrancisi questions
Mon, Feb 21, 22, 00:00, 2 Years ago
Mon, Apr 5, 21, 00:00, 3 Years ago
Thu, Nov 5, 20, 00:00, 4 Years ago
;