Mongoose TypeScript ObjectId 转换 - 类型“string”不可分配给类型“Condition<ObjectId |” 未定义>'

And*_*dre 13 javascript mongoose mongodb node.js typescript

当我通过 ObjectId 字段查询时,我遇到猫鼬查询问题。通过mongoose.Types.ObjectIdstring两者都抛出错误。当我将 ObjectId 转换为 时,TypeScript 才会停止抱怨mongoose.Schema.Types.ObjectId,然后在运行时崩溃,因为它不是有效的 ObjectId。

interface DocumentWithTimestamp extends Document<ObjectId> {
  createdAt: Date;
  updatedAt: Date;
}
Run Code Online (Sandbox Code Playgroud)

首先,我注意到 Document 定义_idObjectId | undefined,这已经使一切变得复杂。

我定义我的架构如下:

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);
Run Code Online (Sandbox Code Playgroud)

现在通过 _id 或任何其他 ObjectId 字段查询我的 LanguageModel 会引发类型错误:

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

错误:

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[]>'.
Run Code Online (Sandbox Code Playgroud)

当我尝试将 string[] 转换为 Schema.Types.ObjectId[] 数组时,错误消失了,但这不是解决方案,因为它在运行时崩溃(Schema.Types.ObjectId 不是有效的 ObjectId)。

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

如果我转换为mongoose.Types.ObjectId(到一个真正的 ObjectId),它会再次抛出错误......

任何帮助表示赞赏!

And*_*dre 8

我找到了解决问题的方法。

mongoose 文件定义如下:

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

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

  // ...
  }
Run Code Online (Sandbox Code Playgroud)

我使用扩展了它Document<ObjectId>。然而,ObjectId 类型是 Schema 类型,例如

import { ObjectId } from "mongoose";
Run Code Online (Sandbox Code Playgroud)

但它实际上应该是 mongoose 的实际 ObjectId 类型,而不是 Schema 类型!

使固定:

import { Types } from "mongoose"

interface DocumentWithTimestamp extends Document<Types.ObjectId> {
  createdAt: Date;
  updatedAt: Date;
}
Run Code Online (Sandbox Code Playgroud)

  • 这里来自 mongoose 的超级混乱的 api....他们需要更好的支持。甚至不知道为什么你必须定义一个模型然后定义一个接口......巨大的痛苦 (5认同)