KeihakuOh / Mini-Microservices-App

0 stars 0 forks source link

section17_memo #19

Open KeihakuOh opened 2 weeks ago

KeihakuOh commented 2 weeks ago

Ticketモデルを使ってドキュメントを初めて保存しようとすると、MongoDBは自動的にticketsという名前のコレクションを作成します(モデル名がTicketなので、その複数形の小文字であるticketsがデフォルトのコレクション名)(MongoDBの「コレクション」は、SQLデータベースの「テーブル」に相当する)

KeihakuOh commented 2 weeks ago

catch(err) は、拒否(reject)された Promise をキャッチして処理するためのメソッド

KeihakuOh commented 2 weeks ago
import mongoose from 'mongoose';
import express, { Request, Response } from 'express';
import { requireAuth, validateRequest } from '@wsbticket/common/build';
import { body } from 'express-validator';

const router = express.Router();

router.post(
  '/api/orders',
  requireAuth,
  [
    body('ticketId')
      .not()
      .isEmpty()
      .custom((input: string) => mongoose.Types.ObjectId.isValid(input))
      .withMessage('TicketId must be provided'),
  ],
  validateRequest,
  async (req: Request, res: Response) => {
    res.send({});
  }
);

export { router as newOrderRouter };
import { Request, Response, NextFunction } from "express";
import { validationResult } from "express-validator"; 
import { RequestValidationError } from "../errors/request-validation-error";

export const validateRequest = (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  const errors = validationResult(req);

  if (!errors.isEmpty()) {
    throw new RequestValidationError(errors.array());
  }

  next();
};

[ body('ticketId') .not() .isEmpty() .custom((input: string) => mongoose.Types.ObjectId.isValid(input)) .withMessage('TicketId must be provided'), ], validateRequest,

[ body('ticketId') .not() .isEmpty() .custom((input: string) => mongoose.Types.ObjectId.isValid(input)) .withMessage('TicketId must be provided'), ],はバリデーションを追加して、実際判断するのはvalidateRequestのvalidationResult(req)

KeihakuOh commented 2 weeks ago
import mongoose from 'mongoose';

interface OrderAttrs {
  userId: string;
  status: string;
  expiresAt: Date;
  ticket: TicketDoc;
}

interface OrderDoc extends mongoose.Document {
  userId: string;
  status: string;
  expiresAt: Date;
  ticket: TicketDoc;
}

interface OrderModel extends mongoose.Model<OrderDoc> {
  build(attrs: OrderAttrs): OrderDoc;
}

const orderSchema = new mongoose.Schema(
  {
    userId: {
      type: String,
      required: true,
    },
    status: {
      type: String,
      required: true,
    },
    expiresAt: {
      type: mongoose.Schema.Types.Date,
    },
    ticket: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'Ticket',
    },
  },
  {
    toJSON: {
      transform(doc, ret) {
        ret.id = ret._id;
        delete ret._id;
      },
    },
  }
);

orderSchema.statics.build = (attrs: OrderAttrs) => {
  return new Order(attrs);
};

const Order = mongoose.model<OrderDoc, OrderModel>('Order', orderSchema);

export { Order };

TicketDoc: データベースに保存されたチケットを操作するときに使う。Mongooseが自動的に追加するフィールド(_id、createdAt、updatedAtなど)も含まれるため、これらの情報を扱うことができる

TicketDoc: データベースに保存されたチケットを操作するときに使う。Mongooseが自動的に追加するフィールド(_id、createdAt、updatedAtなど)も含まれるため、これらの情報を扱うことができる

const Order = mongoose.model<OrderDoc, OrderModel>('Order', orderSchema);がないとorderSchema.statics.build = (attrs: OrderAttrs) => { return new Order(attrs); };はエラーになる

KeihakuOh commented 2 weeks ago

enum

enum Direction {
  Up = "UP",
  Down = "DOWN",
  Left = "LEFT",
  Right = "RIGHT",
}

let currentDirection: Direction = Direction.Up;

console.log(currentDirection); // 出力: "UP"

if (currentDirection === Direction.Up) {
  console.log("Going up!");
}
KeihakuOh commented 2 weeks ago
const orderSchema = new mongoose.Schema(
  {
    userId: {
      type: String,
      required: true,
    },
    status: {
      type: String,
      required: true,
    },
    expiresAt: {
      type: mongoose.Schema.Types.Date,
    },
    ticket: {
      type: mongoose.Schema.Types.ObjectId, // 他のコレクションのドキュメントを参照するための ObjectId 型
      ref: 'Ticket', // Ticket コレクションを参照
    },
  },
  {
    toJSON: {
      transform(doc, ret) {
        ret.id = ret._id;
        delete ret._id;
      },
    },
  }
);

ticket: { type: mongoose.Schema.Types.ObjectId, // 他のコレクションのドキュメントを参照するための ObjectId 型 ref: 'Ticket', // Ticket コレクションを参照 }, Ticketのidだけ保存して、それを使って関連付けしている

KeihakuOh commented 2 weeks ago
import mongoose from 'mongoose';
import { Order, OrderStatus } from './order';

interface TicketAttrs {
  title: string;
  price: number;
}

export interface TicketDoc extends mongoose.Document {
  title: string;
  price: number;
  isReserved(): Promise<boolean>;
}

interface TicketModel extends mongoose.Model<TicketDoc> {
  build(attrs: TicketAttrs): TicketDoc;
}

const ticketSchema = new mongoose.Schema(
  {
    title: {
      type: String,
      required: true,
    },
    price: {
      type: Number,
      required: true,
      min: 0,
    },
  },
  {
    toJSON: {
      transform(doc, ret) {
        ret.id = ret._id;
        delete ret._id;
      },
    },
  }
);

ticketSchema.statics.build = (attrs: TicketAttrs) => {
  return new Ticket(attrs);
};
ticketSchema.methods.isReserved = async function () {
  // this === the ticket document that we just called 'isReserved' on
  const existingOrder = await Order.findOne({
    ticket: this,
    status: {
      $in: [
        OrderStatus.Created,
        OrderStatus.AwaitingPayment,
        OrderStatus.Complete,
      ],
    },
  });

  return !!existingOrder;
};

const Ticket = mongoose.model<TicketDoc, TicketModel>('Ticket', ticketSchema);

export { Ticket };

isReserved() が個々のチケットドキュメント(TicketDoc)に対して動作するインスタンスメソッドだから ・モデルは MongoDB のコレクション全体に対する操作を行うクラスのようなもの ・ドキュメントは、MongoDB のコレクション内の個々のレコードに対応するオブジェクト

KeihakuOh commented 1 week ago

process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; 目的: HTTPSリクエストの際に、自己署名証明書や信頼されていない証明書を許可するように設定

KeihakuOh commented 1 week ago

orders コレクション(注文)
{
  "_id": "order1",
  "userId": "user1",
  "ticket": "ticket1"
}
tickets コレクション(チケット):
{
  "_id": "ticket1",
  "title": "Concert A",
  "price": 100
}
const orders = await Order.find({
  userId: req.currentUser!.id, // 現在のユーザーの注文を取得
}).populate('ticket'); // 'ticket' フィールドをポピュレート
結果:
{
  "_id": "order1",
  "userId": "user1",
  "ticket": {
    "_id": "ticket1",
    "title": "Concert A",
    "price": 100
  }
}
KeihakuOh commented 1 week ago
import mongoose from 'mongoose';
import { Order, OrderStatus } from './order';

interface TicketAttrs {
  title: string;
  price: number;
}

export interface TicketDoc extends mongoose.Document {
  title: string;
  price: number;
  isReserved(): Promise<boolean>;
}

interface TicketModel extends mongoose.Model<TicketDoc> {
  build(attrs: TicketAttrs): TicketDoc;
}

const ticketSchema = new mongoose.Schema(
  {
    title: {
      type: String,
      required: true,
    },
    price: {
      type: Number,
      required: true,
      min: 0,
    },
  },
  {
    toJSON: {
      transform(doc, ret) {
        ret.id = ret._id;
        delete ret._id;
      },
    },
  }
);

ticketSchema.statics.build = (attrs: TicketAttrs) => {
  return new Ticket(attrs);
};
ticketSchema.methods.isReserved = async function () {
  // this === the ticket document that we just called 'isReserved' on
  const existingOrder = await Order.findOne({
    ticket: this,
    status: {
      $in: [
        OrderStatus.Created,
        OrderStatus.AwaitingPayment,
        OrderStatus.Complete,
      ],
    },
  });

  return !!existingOrder;
};

const Ticket = mongoose.model<TicketDoc, TicketModel>('Ticket', ticketSchema);

export { Ticket };

TicketAttrsはbuild用のインタフェース、TicketDoc, TicketModeはモデル側の、'Ticket'はコレクション(SQL側のデータベース)