mongodb - Saknade deldokumentmetoder i Mongoose med Typescript


Jag arbetar på ett projekt och behöver hämta specifika underdokument från en modell genom deras underdokument _id. Jag planerar sedan att göra uppdateringar på dessa underdokument och spara huvudokumentet. Mongoose underdokumentdokumentationen listar ett antal metoder du kan kalla på parent.children-arrayen, men metoder som inte redan finns i Javascript för arrayer ger ett felmeddelande som säger att de inte finns och det kompilerar inte. Jag refererar till denna dokumentation: https://mongoosejs.com/docs/subdocs.html

Jag förstår att jag bör kunna använda .findOneAndUpdate för att göra mina uppdateringar, och med alternativet runValidators bör allt fortfarande valideras, men jag skulle också vilja bara hämta underdokumentet självt.

Jag tittade på det här inlägget: MongoDB, Mongoose: Hur hittar man ett subdokument i ett hittat dokument?, och jag vill kommentera att svaret är felaktigt: om ett subdokumentschema registreras skapas det inte automatiskt en collection för det schemat, collectionen skapas bara om det schemat sparas separat. Du kan inte använda ChildModel.findOne() och hämta ett subdokument, eftersom collectionen inte existerar, det finns ingenting i den.

Att låta IChildModel utöka mongoose.Types.Subdocument och låta IParent-gränssnittet referera till det istället för IChild och inte registrera ChildModel ändrar ingenting annat än att det inte längre tillåter anrop till .push() att inte acceptera enkla objekt (som saknar cirka 30 egenskaper). Att även försöka mongoose.Types.Array<IChild> i IParent-gränssnittet på detta sätt ändrar heller ingenting.

Att ändra IParent-gränssnittet för att använda mongoose.Types.Array<IChild> för children-egenskapen gör att addToSet() fungerar, men inte id() eller create()

Jag använder Mongoose version 5.5.10, MongoDb version 4.2.0 och Typescript version 3.4.5

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

Svar #1

Lite sent svar, men jag tittade igenom typerna och hittade DocumentArray

import { Document, Embedded, Types } from 'mongoose';
interface IChild extends Embedded {
    name: string;
}

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

Ville bara sätta detta här ifall någon annan behöver det.

Relaterade artiklar