mongoosetypescript方式......?

IT技术 javascript node.js mongoose typescript
2021-02-04 14:41:24

尝试在 Typescript 中实现 Mongoose 模型。搜索 Google 只发现了一种混合方法(结合 JS 和 TS)。在没有 JS 的情况下,如何以我相当天真的方法实现 User 类?

想要能够没有包袱的IUserModel。

import {IUser} from './user.ts';
import {Document, Schema, Model} from 'mongoose';

// mixing in a couple of interfaces
interface IUserDocument extends IUser,  Document {}

// mongoose, why oh why '[String]' 
// TODO: investigate out why mongoose needs its own data types
let userSchema: Schema = new Schema({
  userName  : String,
  password  : String,
  firstName : String,
  lastName  : String,
  email     : String,
  activated : Boolean,
  roles     : [String]
});

// interface we want to code to?
export interface IUserModel extends Model<IUserDocument> {/* any custom methods here */}

// stumped here
export class User {
  constructor() {}
}
6个回答

这是我的方法:

export interface IUser extends mongoose.Document {
  name: string; 
  somethingElse?: number; 
};

export const UserSchema = new mongoose.Schema({
  name: {type:String, required: true},
  somethingElse: Number,
});

const User = mongoose.model<IUser>('User', UserSchema);
export default User;
像这样的东西: import User from '~/models/user'; User.find(/*...*/).then(/*...*/);
2021-03-15 14:41:24
最后一行(导出默认 const 用户...)对我不起作用。我需要按照stackoverflow.com/questions/35821614/...
2021-03-19 14:41:24
抱歉,但是“mongoose”在 TS 中是如何定义的?
2021-04-01 14:41:24
import * as mongoose from 'mongoose'; 或者 import mongoose = require('mongoose');
2021-04-01 14:41:24
我可以let newUser = new User({ iAmNotHere: true })在 IDE 或编译时没有任何错误。那么创建接口的原因是什么?
2021-04-12 14:41:24

如果您想分离您的类型定义和数据库实现,另一种选择。

import {IUser} from './user.ts';
import * as mongoose from 'mongoose';

type UserType = IUser & mongoose.Document;
const User = mongoose.model<UserType>('User', new mongoose.Schema({
    userName  : String,
    password  : String,
    /* etc */
}));

灵感来自这里:https : //github.com/Appsilon/styleguide/wiki/mongoose-typescript-models

是的,这是一个值得考虑的有效论点。不过,使用组件集成测试可能有助于降低风险。请注意,有些方法和体系结构将类型声明和数据库实现分开,无论是通过 ORM(如您所建议的)还是手动(如本答案)完成。没有灵丹妙药... <(°.°)>
2021-03-31 14:41:24
一种可能是从 GraphQL 定义中为 TypeScript 和 mongoose生成代码
2021-04-10 14:41:24
mongoose.Schema此处定义是否与 中的字段重复IUser鉴于它IUser是在不同的文件中定义的,随着项目的复杂性和开发人员数量的增加,字段不同步风险非常高。
2021-04-11 14:41:24

很抱歉发布尸检,但这对某些人来说仍然很有趣。我认为Typegoose提供了更现代和优雅的方式来定义模型

这是文档中的一个示例:

import { prop, Typegoose, ModelType, InstanceType } from 'typegoose';
import * as mongoose from 'mongoose';

mongoose.connect('mongodb://localhost:27017/test');

class User extends Typegoose {
    @prop()
    name?: string;
}

const UserModel = new User().getModelForClass(User);

// UserModel is a regular Mongoose Model with correct types
(async () => {
    const u = new UserModel({ name: 'JohnDoe' });
    await u.save();
    const user = await UserModel.findOne();

    // prints { _id: 59218f686409d670a97e53e0, name: 'JohnDoe', __v: 0 }
    console.log(user);
})();

对于现有的连接场景,您可以使用如下(在实际情况中更有可能并且在文档中未发现):

import { prop, Typegoose, ModelType, InstanceType } from 'typegoose';
import * as mongoose from 'mongoose';

const conn = mongoose.createConnection('mongodb://localhost:27017/test');

class User extends Typegoose {
    @prop()
    name?: string;
}

// Notice that the collection name will be 'users':
const UserModel = new User().getModelForClass(User, {existingConnection: conn});

// UserModel is a regular Mongoose Model with correct types
(async () => {
    const u = new UserModel({ name: 'JohnDoe' });
    await u.save();
    const user = await UserModel.findOne();

    // prints { _id: 59218f686409d670a97e53e0, name: 'JohnDoe', __v: 0 }
    console.log(user);
})();
永远不要为“尸检”道歉。[正如你现在所知...] 甚至还有一个徽章(虽然命名为死灵法师;^D)来做这件事!鼓励发布新信息和想法!
2021-03-17 14:41:24
@ruffin:我也真的不明白反对发布新的和最新的问题解决方案的耻辱。
2021-03-26 14:41:24
@Corbfon 你试过了吗?如果是这样,你的发现是什么?如果没有,是否还有其他原因让您决定不使用它?我通常看到有些人担心完全支持,但似乎实际使用它的人对此非常满意
2021-03-30 14:41:24
@N4ppeL 我不会同意typegoose- 我们最终手动处理我们的打字,类似于这篇文章,看起来ts-mongoose可能有一些Promise(如后面的答案中所建议的)
2021-04-05 14:41:24
我也得出了这个结论,但是担心typegoose没有足够的支持……查看他们的 npm 统计数据,每周只有 3k 下载量,而且 rn 有近 100 个开放的 Github 问题,其中大部分没有评论,其中一些看起来早就应该关闭了
2021-04-13 14:41:24

这里的大多数答案都重复了 TypeScript 类/接口和mongoose模式中的字段。没有单一的真实来源意味着维护风险,因为项目变得更加复杂,并且有更多的开发人员在此工作:字段更有可能不同步当类与mongoose模式位于不同的文件中时,这尤其糟糕。

为了保持字段同步,定义它们一次是有意义的。有几个库可以做到这一点:

我还没有完全相信他们中的任何一个,但 typegoose 似乎得到了积极维护,开发人员接受了我的 PR。

提前考虑一步:当您将 GraphQL 模式添加到组合中时,会出现另一层模型复制。解决这个问题的一种方法可能是从 GraphQL 模式生成 TypeScript 和mongoose代码

如果实体具有 Mongoose 模式中不存在的附加 graphql 字段,则使用 Graphql 生成typescript类型将有问题,因为该类型不仅具有 mongoose 模式字段,而且还具有来自 graphql 的附加字段。
2021-03-23 14:41:24

试试ts-mongoose它使用条件类型来进行映射。

import { createSchema, Type, typedModel } from 'ts-mongoose';

const UserSchema = createSchema({
  username: Type.string(),
  email: Type.string(),
});

const User = typedModel('User', UserSchema);
披露:ts-mongoose 似乎是由天空创造的。似乎是最巧妙的解决方案。
2021-03-19 14:41:24
漂亮的包,你还在维护吗?
2021-03-22 14:41:24
看起来不错,但我们仍然需要 mongoose 来实现 api 中的其他逻辑。
2021-04-13 14:41:24