【问题标题】:How to properly type array of object IDs in mongoose with Typescript如何使用 Typescript 在 mongoose 中正确键入对象 ID 数组
【发布时间】:2021-11-27 17:12:40
【问题描述】:

我有一个帖子模型:

const PostSchema = new Schema<IPost>(
  {
    // ...
    likes: [{ type: Schema.Types.ObjectId, ref: "User" }],
    // ...
  }
)

export default model<IPost>("Post", PostSchema)
export interface IPost {
  // ...
  likes: ObjectId[]
  // ...
}

export interface IPostDocument extends Document, IPost {}

我正在尝试切换用户,例如:

export const toggleLike: TController = async (req, res, next) => {
  const user = req.user as IUserDocument;
  const userId = user._id;
  const postId = req.params.postId;
  try {
    const disliked = await PostModel.findOneAndUpdate(
      { _id: postId, likes: userId },
      { $pull: { likes: userId } }
    ); // works with no problem
    if (disliked)
      res.json({ message: `User ${userId} disliked post ${postId}` });
    else {
      const liked = await PostModel.findOneAndUpdate(
        { _id: postId },
        { $push: { likes: userId } }
      ); // the $push throws an error "Type instantiation is excessively deep and possibly infinite."
      if (liked) res.json({ message: `User ${userId} liked post ${postId}` });
      else return next(createError(404, "Post not found"));
    }
  } catch (error) {
    next(createError(500, error as Error));
  }
};

mongo $push 运算符抛出错误“类型实例化过深并且可能无限。”

我怀疑它是否有帮助,但错误的描述是:

(属性)喜欢?任意[])[] |任意[])[]|任意[])[]|任意[])[]|任意[])[]|任意[])[]|任意[])[]|任意[])[] |任何[]> | ArrayOperator | 未定义)[]> |未定义

知道发生了什么吗?

【问题讨论】:

  • 您介意以有效的 JSON 格式共享示例数据吗?
  • 错误提示数据库中的数据不是单级数组,而是数组数组。实际上可能是数组数组数组数组数组数组数组数组数组等等。
  • 你能添加你的依赖版本的细节吗?我创建了一个最小的复制here,它适用于"mongoose": "^6.0.11"、"@types/mongoose": "^5.11.97" 和"typescript": "^4.4.4"
  • 感谢您的 cmets,但问题已解决。在我的界面上,我使用了 ObjectId,但没有从任何地方导入它。一旦我从猫鼬导入它,一切正常。我不知道我使用的另一个 ObjectId 是什么...

标签: typescript mongodb mongoose


【解决方案1】:

我不确定,但可能会很有趣:类型脚本方面可能期望其他项目出现,因为它以数组的形式聚焦。

您可以尝试使用每个 { $push: { : { $each: [ , ... ] } } }

value1 在你的位置上就足够了

【讨论】:

    【解决方案2】:

    在我的接口声明中从 mongoose 导入 ObjectId 解决了这个问题。在此之前,我一直在使用它,但没有从任何地方导入它(我什至不知道那是什么)。

    【讨论】:

      【解决方案3】:

      我想你的问题与这个我的问题非常相关:Nestjs: Correct schema for array of subdocuments in mongoose (without default _id or redefine ObjectId)。除了我不想拥有ObjectID 但你是。

      问题是MongooseDocument&lt;Array&gt; 和 TS Array 非常相似,但方法不同。

      我正在使用 Nestjs,所以我将提供一个示例,但我想您发现我的示例非常有用。

      例如,对于嵌入文档的数组,您需要具有以下架构接口:

      在子架构中:

      @Schema()
      class Field extends Document {
        @Prop({ type: MongooseSchema.Types.ObjectId })
        _id: MongooseSchema.Types.ObjectId
      
        @Prop({ type: String })
        name: string;
      }
      
      export const FieldSchema = SchemaFactory.createForClass(Field);
      

      在父架构中:

        @Prop({ _id: true, type: [FieldSchema] })
        field: MongooseSchema.Types.Array<Field>;
      

      最重要的部分是导入:

      import { Document, Schema as MongooseSchema, Types } from "mongoose";
      import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
      

      当然,在默认的 TS 项目中,如果没有 Nest.js,您就没有 nest/mongoose,但正如您可能已经理解的那样,一切都与我们从 mongoose 本身获取的接口及其类型相关。

      所以class是一个Schema接口,它是从猫鼬Document接口扩展而来的,所有的数组都不仅仅是普通的TS数组,而是Schema.Types.Array(来自mongoose)。您不仅可以使用 ObjectId,还可以使用其他特殊的 Mongo 专用类型,例如 Decimal128 数字和 Mixed 等等,according to the docs。

      所以在你使用 ObjectIds 数组的情况下,你只需要使用:

      MongooseSchema.Types.Array<MongooseSchema.Types.ObjectId>
      

      或者更原始的方式:

      在 @Prop 装饰器中的 Nest 中,您为 mongoDB 字段类型提供类型,因此它与默认 TS 相同:new Schema({ languages: { type: ObjectId} })

      所以我希望它对你的项目有所帮助。

      【讨论】:

        猜你喜欢
        • 2021-06-15
        • 1970-01-01
        • 2012-09-17
        • 1970-01-01
        • 2021-07-28
        • 2020-09-15
        • 2018-10-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多