✍️
GraphQLスキーマ図模写 オークション編
twitter.comで@kawasimaさんがオークションサイトのスキーマってどんなだろうとつぶやいていたのに対して作ってみたスキーマ図が思いのほか反響があったので、改めて作ってみました。
色んなアプリケーションのスキーマ図を模写して公開してみることで誰かのGraphQLスキーマ作成の参考になればと思ったので公開してみます。
今回のアプリ オークションサイト
某オークションサイトを参考に、妄想でスキーマ図を作成しました。
スキーマ図
API対象利用者
- ゲストユーザー
- 落札者
- 出品者
設計意図
- 掲載情報(Listing)は誰でも見れる
- 取引(Transaction)は出品者か落札者だけが見れる
- 取引から掲載情報は一方通行
- レビューはユーザーから絞り込みして取得する
- 画面毎にログインユーザーを絞り込み条件として情報取得するため、ユーザーから関連する情報はQueryで実現する。
- User Typeは作らない
SDL
SDL
scalar Datetime
type Query {
listings: [Listing!]
ownListings: [Listing!]
watchingListings: [Listing!]
myTransactions: [Transaction!]
transaction(transactionId: Int!): Transaction
reviews(userId: Int!): [Review!]
viewer: Viewer
}
"""
プロフィール
"""
type Profile {
userId:Int!
displayName:String!
iconUrl:String
reviewCount:Int
reviewRate:Float
}
"""
配送住所
"""
type ShippingAddress {
name:String!
postCode:String!
prefecture:Int!
address1:String!
address2:String
phoneNumber:String
}
"""
掲載
"""
type Listing {
ownerId:Int!
listingId:Int!
title:String!
description:String
images:[ListingImage!]!
initialPrice:Int!
currentPrice:Int!
currentTax:Int!
buyoutPrice:Int
startAt:Datetime!
endAt:Datetime!
status:ListingStatus!
shippingMethod:ShippingMethod!
paymentMethod:PaymentMethod!
"""
返品可能
"""
canReturn:Boolean!
"""
自動延長
"""
isAutoExtention:Boolean!
"""
トップカテゴリーからのカテゴリーリスト
"""
categoriesFromTop:[Category!]!
ownerProfile:Profile!
currentBidding:Bidding
closingBidding:Bidding
biddings:[Bidding!]!
biddingCount:Int!
watchCount:Int
"""
ウォッチしているか
"""
isWatching:Boolean!
}
"""
入札
"""
type Bidding {
bidderId:Int!
price:Int!
biddingAt:Datetime!
status:BiddingStatus!
bidderProfile:Profile!
}
"""
取引
"""
type Transaction {
transactionId:Int!
status:TransactionStatus!
myRole:TransactionRole!
listing:Listing!
price:Int!
shippingMethod:PaymentMethod!
shippingAddress:ShippingAddress!
shippingAmount:Int!
totalAmount:Int!
ownerProfile:Profile!
bidderProfile:Profile!
messages:[Message!]
ownerReview:Review
bidderReview:Review
}
"""
メッセージ
"""
type Message {
messageId:Int!
content:String
sentAt:Datetime!
sentBy:TransactionRole!
}
"""
カテゴリー
"""
type Category {
categoryId:Int!
name:String!
childrenCategories:[Category]
}
"""
商品画像
"""
type ListingImage {
url:String!
alt:String
}
"""
レビュー
"""
type Review {
reviewId:Int!
rate:Int!
comment:String
transactionRole:TransactionRole!
createdAt:Datetime!
listing:Listing!
}
"""
閲覧者
"""
type Viewer {
userId:Int!
displayName:String!
iconUrl:String
}
enum ListingStatus {
OPEN
CLOSED
CANCELED
}
enum TransactionRole {
BIDDER
OWNER
}
enum TransactionStatus {
ONGOING
FINISHED
CANCELED
}
enum ListingCondition {
NEW
OLD
}
enum ShippingMethod {
POST
SELF
}
enum PaymentMethod {
CREDIT_CARD
BANK
}
enum BiddingStatus {
ELECTED
UNELECTED
CANCELED
}
graphql-voyagerにSDLを貼ると閲覧しやすいです。
オペレーション
商品一覧
query ListingList {
listings {
listingId
ownerId
title
description
currentPrice
biddingCount
watchiCount
isWatching
startAt
endAt
}
}
商品詳細
query ListingDetail {
listings {
ownerId
listingId
title
description
images
initialPrice
currentPrice
currentTax
buyoutPrice
startAt
endAt
status
shippingMethod
paymentMethod
canReturn
isAutoExtention
categoriesFromTop {
categoryId
name
}
ownerProfile {
userId
displayName
iconUrl
reviewCount
reviewRate
}
currentBidding {
bidderId
price
biddingAt
bidderProfile {
userId
displayName
iconUrl
reviewCount
reviewRate
}
}
biddingCount
watchCount
isWatching
}
}
取引一覧
query MyTransactions {
myTransactions {
transactionId
status
myRole
listing {
listingId
title
images {
url
}
}
closingBidding {
bidderId
price
biddingAt
status
}
price
ownerProfile {
userId
displayName
iconUrl
}
bidderProfile {
userId
displayName
iconUrl
}
ownerReview {
reviewId
rate
comment
createdAt
}
bidderReview {
reviewId
rate
comment
createdAt
}
}
}
取引詳細
query Transaction($transactionId: Int!) {
transaction(transactionId: $transactionId) {
transactionId
status
myRole
listing {
listingId
title
images {
url
}
}
closingBidding {
bidderId
price
biddingAt
status
}
price
ownerProfile {
userId
displayName
iconUrl
}
bidderProfile {
userId
displayName
iconUrl
}
messages {
messageId
content
sentAt
sentBy
}
ownerReview {
reviewId
rate
comment
createdAt
}
bidderReview {
reviewId
rate
comment
createdAt
}
}
}
レビュー一覧
query Reviews($userId: Int!) {
reviews(userId: $userId) {
reviewId
rate
comment
transactionRole
createdAt
listing {
listingId
title
images {
url
}
}
}
}
ログインユーザー情報
query Viewer {
userId
displayName
iconUrl
}
雑感
オークションサイトの特性
- 特徴: Read Heavy
- ユーザーの滞在時間: 短い
- ユーザーによる操作: 少ない
- クライアントの状態の変化: 少ない
- データの種類: 少ない
- データの関連性: 少ない
- 未来のAPIの拡張必要性: 低い
- 未来のAPIの変化可能性: 低い
オークションサイトの特性上、どれもGraphQLを必要とする特性がないためREST APIで十分問題なさそう。GraphQL APIで提供する場合でも Persisted Queryを利用してGETリクエストでHTTPのキャッシュが効くように運用する。
おわりに
フィードバックや質問があればディスカッションしましょう。みなさまのGraphQLの理解に役立てれば幸いです。需要があればまた別のアプリケーションでやります。
Discussion