首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有Typescript的Mongoose中缺少Subdocument方法

带有Typescript的Mongoose中缺少Subdocument方法
EN

Stack Overflow用户
提问于 2019-08-29 02:42:50
回答 2查看 2.3K关注 0票数 4

我正在做一个项目,需要通过它们的子文档_id从模型中检索特定的子文档。然后,我计划对这些子文档进行更新并保存主文档。Mongoos子文档文档列出了许多可以在parent.children数组上调用的方法,但是在Javascript for arrays中不存在的方法会给出一个错误,说它们不存在并且无法编译。我引用这个文档:https://mongoosejs.com/docs/subdocs.html

我知道应该能够使用.findOneAndUpdate进行更新,并且使用runValidators选项仍然可以验证所有内容,但我也希望只检索子文档本身。

我看了这篇文章:MongoDB, Mongoose: How to find subdocument in found document?,我会评论说答案是不正确的,如果注册了一个子文档模式,它会自动为该模式创建一个集合,只有当该模式单独保存时才会创建该集合。不能使用ChildModel.findOne()并检索子文档,因为集合不存在,其中没有任何内容。

IChildModel扩展mongoose.Types.Subdocument,让IParent接口引用而不是IChild,并且不注册ChildModel,除了不再允许对.push()的调用不接受简单对象(缺少大约30个属性)之外,不会改变任何事情。此外,使用此方法在IParent接口中尝试mongoose.Types.Array<IChild>不会更改任何内容。

IParent接口更改为对children属性使用mongoose.Types.Array<IChild>将允许addToSet()工作,但不允许id()create()工作

我用的是Mongoose版本5.5.10,MongoDb版本4.2.0和Typescript版本3.4.5

代码语言:javascript
复制
import mongoose, { Document, Schema } from "mongoose";

// Connect to mongoDB with mongoose
mongoose.connect(process.env.MONGO_HOST + "/" + process.env.DB_NAME, {useNewUrlParser: true, useFindAndModify: false});

// Interfaces to be used throughout application
interface IParent {
    name: string;
    children: IChild[];
}

interface IChild {
    name: string;
    age: number;
}

// Model interfaces which extend Document
interface IParentModel extends IParent, Document { }
interface IChildModel extends IChild, Document { }

// Define Schema
const Child: Schema = new Schema({
    name: {
        type: String,
        required: true
    },
    age: {
        type: Number,
        required: true
    }
});

const ChildSchema: Schema = Child;

const Parent: Schema = new Schema({
    name: {
        type: String,
        required: true
    },
    children: [ChildSchema]
});

const ParentSchema: Schema = Parent;

// Create the mongoose models
const ParentModel = mongoose.model<IParentModel>("Parent", Parent);
const ChildModel = mongoose.model<IChildModel>("Child", Child);

// Instantiate instances of both models
const child = new ChildModel({name: "Lisa", age: 7});
const parent = new ParentModel({name: "Steve", children: [child]});

const childId = child._id;

// Try to use mongoose subdocument methods
const idRetrievedChild = parent.children.id(childId); // Property 'id' does not exist on type 'IChild[]'.ts(2339)
parent.children.addToSet({ name: "Liesl", age: 10 }); // Property 'addToSet' does not exist on type 'IChild[]'.ts(2339)
parent.children.create({ name: "Steve Jr", age: 2 }); // Property 'create' does not exist on type 'IChild[]'.ts(2339)

// If I always know the exact position in the array of what I'm looking for
const arrayRetrievedChild = parent.children[0]; // no editor errors
parent.children.unshift(); // no editor errors
parent.children.push({ name: "Emily", age: 18 }); // no editor errors
EN

回答 2

Stack Overflow用户

发布于 2020-09-10 22:47:05

响应有点晚,但我检查了一下类型,找到了DocumentArray

代码语言:javascript
复制
import { Document, Embedded, Types } from 'mongoose';
interface IChild extends Embedded {
    name: string;
}

interface IParent extends Document {
    name: string;
    children: Types.DocumentArray<IChild>;
}

只是想把这个放在这里以防其他人需要它。

票数 10
EN

Stack Overflow用户

发布于 2019-08-29 05:48:51

Gross:现在,我使用了一个非常快速和肮脏的polyfill解决方案,实际上并没有回答我的问题:

代码语言:javascript
复制
declare module "mongoose" {
    namespace Types {
        class Collection<T> extends mongoose.Types.Array<T> {
            public id: (_id: string) => (T | null);
        }
    }
}

然后我们这样声明IParent

代码语言:javascript
复制
interface IParent {
    name: string;
    children: mongoose.Types.Collection<IChild>;
}

因为函数id()已经存在,而typescript并不知道它,所以代码可以工作,polyfill让它编译。

甚至Grosser:另外,为了获得更快更脏的解决方案,当您创建父模型实例时,只需将其类型转换为any,并丢弃所有类型检查:

代码语言:javascript
复制
const child = new ChildModel({name: "Lisa", age: 7});
const parent: any = new ParentModel({name: "Steve", children: [child]});
const idRetrievedChild = parent.children.id(childId); // works because declared any
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57698371

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档