กําหนดเอนทิตีสําหรับ REST และ GraphQL

เสร็จสมบูรณ์เมื่อ

เอนทิตีเป็นส่วนประกอบหลักของ Data API Builder แต่ละเอนทิตีแมปกับออบเจ็กต์ฐานข้อมูลและกําหนดลักษณะที่ออบเจ็กต์นั้นปรากฏผ่าน REST และ GraphQL API ของคุณ เมื่อคุณกําหนดเอนทิตีอย่างถูกต้อง คุณจะควบคุมได้ว่าลูกค้าสามารถเข้าถึงข้อมูลใดได้บ้าง

ส่วนนี้ entities สร้างขึ้นจากแฟ้มการกําหนดค่าที่คุณสร้างขึ้น เป็นที่ที่คุณระบุตาราง มุมมอง และวัตถุฐานข้อมูลอื่นๆ ที่ DAB แสดง คุณกําหนดค่าแต่ละเอนทิตีด้วยการแม็ปต้นทาง การกําหนดเองฟิลด์ และข้อกําหนดความสัมพันธ์ที่กําหนดพื้นผิว API ของคุณ

ตัวอย่างทั่วทั้งหน่วยนี้ใช้ตารางฐานข้อมูลตัวอย่างต่อไปนี้ โปรดคํานึงถึงคําจํากัดความเหล่านี้ในขณะที่คุณทํางานผ่านการกําหนดค่าแต่ละรายการ:

CREATE TABLE dbo.Categories (
    CategoryID INT PRIMARY KEY,
    CategoryName NVARCHAR(50) NOT NULL
);

CREATE TABLE dbo.Products (
    ProductID INT PRIMARY KEY,
    ProductName NVARCHAR(100) NOT NULL,
    UnitPrice DECIMAL(10, 2) NOT NULL,
    UnitsInStock INT NOT NULL,
    CategoryID INT FOREIGN KEY REFERENCES dbo.Categories(CategoryID)
);

แมปออบเจ็กต์ฐานข้อมูลกับเอนทิตี

ข้อกําหนดของเอนทิตีเริ่มต้นด้วยชื่อและการอ้างอิงแหล่งที่มา ชื่อเอนทิตีจะกลายเป็นตัวระบุที่ใช้ในตําแหน่งข้อมูล API และคิวรี GraphQL ในขณะที่แหล่งที่มาชี้ไปยังออบเจ็กต์ฐานข้อมูลจริง

"entities": {
  "Product": {
    "source": {
      "object": "dbo.Products",
      "type": "table"
    },
    "permissions": [
      {
        "role": "anonymous",
        "actions": ["read"]
      }
    ]
  }
}

การตั้งค่าคอนฟิกนี้แสดง dbo.Products ตารางเป็น Product เอนทิตี ไคลเอ็นต์ REST เข้าถึงได้ที่ /api/Productในขณะที่ไคลเอ็นต์ GraphQL สืบค้นเป็น product (เอกพจน์) หรือ products (พหูพจน์) DAB จะสร้างแบบแผนการตั้งชื่อเหล่านี้โดยอัตโนมัติตามชื่อเอนทิตีของคุณ

typeคุณสมบัติระบุชนิดออบเจ็กต์ฐานข้อมูล: table, , viewหรือ stored-procedure. แต่ละประเภทมีความสามารถที่แตกต่างกัน ตารางสนับสนุนการดําเนินการ CRUD เต็มรูปแบบ (สร้าง อ่าน อัปเดต ลบ) มุมมองโดยทั่วไปสนับสนุนการดําเนินการอ่าน และกระบวนงานที่เก็บไว้จะเรียกใช้ตรรกะแบบกําหนดเอง

กําหนดค่าการแม็ปฟิลด์และนามแฝง

บางครั้งชื่อคอลัมน์ฐานข้อมูลของคุณไม่ตรงกับแบบแผนการตั้งชื่อที่คุณต้องการใน API ของคุณ การแมปฟิลด์ช่วยให้คุณเปลี่ยนชื่อคอลัมน์และควบคุมฟิลด์ที่จะปรากฏในการตอบกลับ API

"Product": {
  "source": {
    "object": "dbo.Products",
    "type": "table"
  },
  "mappings": {
    "ProductID": "id",
    "ProductName": "name",
    "UnitPrice": "price",
    "UnitsInStock": "stockQuantity"
  },
  "permissions": [
    {
      "role": "anonymous",
      "actions": ["read"]
    }
  ]
}

ด้วยการแมปเหล่านี้ ไคลเอ็นต์จะเห็น id, name, , priceและ stockQuantity ในการตอบกลับ API แทนชื่อคอลัมน์ฐานข้อมูลเดิม วิธีนี้ช่วยให้คุณนําเสนอ API ที่สะอาดและสอดคล้องกันในขณะที่ยังคงรักษาสคีมาฐานข้อมูลที่มีอยู่ของคุณไว้ไม่เปลี่ยนแปลง

Note

เมื่อคุณใช้การแม็ปฟิลด์ ไคลเอ็นต์ต้องใช้ชื่อที่แม็ปในการสืบค้นและการกลายพันธุ์ ชื่อคอลัมน์ฐานข้อมูลเดิมจะกลายเป็นรายละเอียดการใช้งานภายใน

เปิดใช้งานการแคชเพื่อประสิทธิภาพที่ดีขึ้น

การแคช Data API Builder ช่วยลดภาระฐานข้อมูลโดยการจัดเก็บผลลัพธ์การสืบค้นชั่วคราว คุณสามารถกําหนดค่าการแคชได้ทั้งในระดับส่วนกลาง (ในส่วนรันไทม์) และต่อเอนทิตีสําหรับการควบคุมแบบละเอียด

"Product": {
  "source": {
    "object": "dbo.Products",
    "type": "table"
  },
  "rest": {
    "enabled": true
  },
  "graphql": {
    "enabled": true,
    "cache": {
      "enabled": true,
      "ttl-seconds": 60
    }
  },
  "permissions": [...]
}

ttl-secondsคุณสมบัติ (เวลาที่ใช้งานจริง) จะกําหนดระยะเวลาที่ข้อมูลที่แคชยังคงใช้ได้ สําหรับแค็ตตาล็อกผลิตภัณฑ์ที่มีการเปลี่ยนแปลงไม่บ่อยนัก ระยะเวลาแคชที่นานขึ้นจะช่วยปรับปรุงประสิทธิภาพการทํางาน สําหรับข้อมูลที่เปลี่ยนแปลงอย่างรวดเร็ว เช่น การนับสินค้าคงคลัง ให้ใช้ระยะเวลาที่สั้นลงหรือปิดใช้งานการแคช

การแคชทํางานแตกต่างกันสําหรับ REST และ GraphQL การแคช REST จะพิจารณา URL ที่สมบูรณ์รวมถึงพารามิเตอร์การสืบค้น ในขณะที่การแคช GraphQL จะตรวจสอบโครงสร้างการสืบค้น ทั้งคู่เคารพ TTL ที่คุณกําหนดค่า

ใช้การแบ่งหน้าสําหรับชุดข้อมูลขนาดใหญ่

เมื่อเอนทิตีมีเรกคอร์ดจํานวนมาก การส่งคืนเรกคอร์ดทั้งหมดในการตอบสนองครั้งเดียวจะสร้างปัญหาด้านประสิทธิภาพและการใช้งาน Data API Builder ให้การสนับสนุนการแบ่งหน้าในตัวที่คุณสามารถปรับแต่งได้ตามเอนทิตี

"Product": {
  "source": {
    "object": "dbo.Products",
    "type": "table"
  },
  "rest": {
    "enabled": true,
    "path": "/products"
  },
  "graphql": {
    "enabled": true,
    "type": {
      "singular": "product",
      "plural": "products"
    }
  },
  "permissions": [...]
}

ไคลเอ็นต์ REST ใช้พารามิเตอร์คิวรี เช่น $first และ $after เพื่อนําทางผ่านหน้า:

GET /api/products?$first=10
GET /api/products?$first=10&$after=eyJQcm9kdWN0SUQiOjEwfQ==

$afterพารามิเตอร์ประกอบด้วยเคอร์เซอร์ที่ชี้ไปยังรายการสุดท้ายจากหน้าก่อนหน้า DAB จะสร้างเคอร์เซอร์เหล่านี้โดยอัตโนมัติตามคีย์หลักของเอนทิตีของคุณ

ไคลเอ็นต์ GraphQL ใช้การแบ่งหน้าที่คล้ายกันผ่านอาร์กิวเมนต์ first และ after ในคิวรี:

query {
  products(first: 10, after: "eyJQcm9kdWN0SUQiOjEwfQ==") {
    items {
      id
      name
      price
    }
    hasNextPage
    endCursor
  }
}

การตอบกลับประกอบด้วยhasNextPageendCursorและฟิลด์ที่ไคลเอ็นต์ใช้เพื่อตรวจสอบว่ามีข้อมูลเพิ่มเติมหรือไม่และจะดึงข้อมูลได้อย่างไร

กําหนดค่าการกรองและการค้นหา

Data API Builder สร้างความสามารถในการกรองโดยอัตโนมัติตามฟิลด์ของเอนทิตีของคุณ ลูกค้าสามารถกรองผลลัพธ์โดยใช้ตัวดําเนินการเปรียบเทียบมาตรฐาน

สําหรับจุดสิ้นสุด REST การกรองจะใช้ไวยากรณ์แบบสอบถามสไตล์ OData:

GET /api/products?$filter=price gt 100 and stockQuantity gt 0

สําหรับ GraphQL การกรองจะใช้วัตถุอินพุตที่พิมพ์:

query {
  products(filter: { price: { gt: 100 }, stockQuantity: { gt: 0 } }) {
    items {
      id
      name
      price
    }
  }
}

DAB สร้างชนิดตัวกรองสําหรับแต่ละฟิลด์ตามชนิดข้อมูล ฟิลด์ตัวเลขรองรับ gt, gte, , lt, lte, eqและ neq. เขตข้อมูลสตริงเพิ่ม contains, startsWith, และendsWith คุณไม่จําเป็นต้องกําหนดค่าความสามารถเหล่านี้อย่างชัดเจน จะพร้อมใช้งานโดยอัตโนมัติสําหรับฟิลด์ที่เปิดเผยทั้งหมด

เคล็ดลับ

สําหรับสถานการณ์การกรองที่ซับซ้อนซึ่งไม่สามารถแสดงผ่านตัวดําเนินการมาตรฐาน ให้พิจารณาสร้างมุมมองหรือกระบวนงานที่เก็บไว้ที่ห่อหุ้มตรรกะการกรอง จากนั้นแสดงเป็นเอนทิตีแยกต่างหาก

กําหนดความสัมพันธ์ของเอนทิตีสําหรับ GraphQL

จุดแข็งของ GraphQL อยู่ที่การสํารวจความสัมพันธ์ระหว่างเอนทิตีในคิวรีเดียว Data API Builder รองรับการกําหนดความสัมพันธ์ที่แมปกับความสัมพันธ์คีย์นอกของฐานข้อมูลของคุณ

"entities": {
  "Product": {
    "source": { "object": "dbo.Products", "type": "table" },
    "relationships": {
      "category": {
        "cardinality": "one",
        "target.entity": "Category",
        "source.fields": ["CategoryID"],
        "target.fields": ["CategoryID"]
      }
    },
    "permissions": [...]
  },
  "Category": {
    "source": { "object": "dbo.Categories", "type": "table" },
    "relationships": {
      "products": {
        "cardinality": "many",
        "target.entity": "Product",
        "source.fields": ["CategoryID"],
        "target.fields": ["CategoryID"]
      }
    },
    "permissions": [...]
  }
}

ด้วยการกําหนดค่าความสัมพันธ์เหล่านี้ ไคลเอ็นต์ GraphQL สามารถสอบถามระหว่างเอนทิตีได้:

query {
  products {
    items {
      name
      price
      category {
        name
      }
    }
  }
}

คุณสมบัติจะ cardinality บ่งชี้ว่าความสัมพันธ์ส่งกลับหนึ่งรายการหรือหลายรายการ ใช้สําหรับ one ความสัมพันธ์แบบกลุ่มต่อหนึ่ง (ผลิตภัณฑ์กับประเภท) และ many สําหรับความสัมพันธ์แบบหนึ่งต่อกลุ่ม (ประเภทกับผลิตภัณฑ์)

ทําความเข้าใจการสร้างปลายทาง REST

เมื่อคุณกําหนดเอนทิตี DAB จะสร้างจุดสิ้นสุด REST โดยอัตโนมัติตามแบบแผนมาตรฐาน แต่ละเอนทิตีจะได้รับเส้นทาง URL พื้นฐาน และคํากริยา HTTP จะแมปกับการดําเนินการ CRUD

สําหรับเอนทิตีที่ตั้งชื่อ Product ด้วยการตั้งค่าคอนฟิกเริ่มต้น:

วิธีการ HTTP รูปแบบ URL การผ่าตัด
GET /api/Product แสดงรายการผลิตภัณฑ์ทั้งหมด (แบ่งหน้า)
GET /api/Product/id/123 รับสินค้าพร้อมรหัส 123
POST /api/Product สร้างผลิตภัณฑ์ใหม่
สำรอง /api/Product/id/123 ปรับปรุงหรือสร้างผลิตภัณฑ์ 123
แก้ไข /api/Product/id/123 ปรับปรุงผลิตภัณฑ์บางส่วน 123
DELETE /api/Product/id/123 ลบสินค้า 123

/id/กลุ่มใน URL บ่งชี้ถึงการค้นหาคีย์หลัก สําหรับคีย์คอมโพสิต ให้เชื่อมโยงเซ็กเมนต์คีย์หลายเซ็กเมนต์: /api/OrderDetail/orderId/100/productId/50.

ปรับแต่งเส้นทางปลายทาง REST

คุณสามารถปรับเปลี่ยนรูปแบบ URL เริ่มต้นผ่านการกําหนดค่าเอนทิตี ส่วนนี้ rest ควบคุมลักษณะการทํางานเฉพาะของ REST:

"Product": {
  "source": { "object": "dbo.Products", "type": "table" },
  "rest": {
    "enabled": true,
    "path": "/products",
    "methods": {
      "get": true,
      "post": true,
      "put": false,
      "patch": true,
      "delete": true
    }
  },
  "permissions": [...]
}

พร็อพเพอร์ตี้pathจะเปลี่ยน URL จาก /api/Product เป็น/api/products การตั้งค่านี้มีประโยชน์เมื่อคุณต้องการชื่อปลายทางที่เป็นตัวพิมพ์เล็กและพหูพจน์ที่แตกต่างจากชื่อเอนทิตีของคุณ

ออบเจ็กต์ช่วยให้คุณสามารถ methods เปิดหรือปิดใช้งานคํากริยา HTTP ที่เฉพาะเจาะจงได้ ในตัวอย่าง PUT นี้ ถูกปิดใช้งาน ซึ่งจะป้องกันการแทนที่ระเบียนทั้งหมดในขณะที่ยังคงอนุญาตให้ PATCH มีการปรับปรุงบางส่วน รูปแบบการกําหนดค่านี้ป้องกันการสูญหายของข้อมูลโดยไม่ได้ตั้งใจจากไคลเอ็นต์ที่อาจส่งเรกคอร์ดที่ไม่สมบูรณ์

เคล็ดลับ

วิธีการปิดใช้งานในระดับปลายทางให้การป้องกันในเชิงลึก แม้ว่าสิทธิ์จะอนุญาตให้ดําเนินการได้ แต่การปิดใช้งานวิธีการจะป้องกันไม่ให้ดําเนินการทั้งหมด

ตั้งค่าการกําหนดค่าตําแหน่งข้อมูล GraphQL

GraphQL ทํางานผ่านปลายทางเดียว ซึ่งโดยทั่วไปจะอยู่ที่ /graphql. คิวรี การกลายพันธุ์ และการสมัครใช้งานทั้งหมดจะผ่านจุดสิ้นสุดนี้ โดยมีเนื้อหาคําขอระบุการดําเนินการ

"runtime": {
  "graphql": {
    "enabled": true,
    "path": "/graphql",
    "allow-introspection": true,
    "depth-limit": 8,
    "multiple-mutations": {
      "create": { "enabled": true }
    }
  }
}

allow-introspectionการตั้งค่าจะควบคุมว่าไคลเอ็นต์สามารถสืบค้น Schema GraphQL ได้หรือไม่ ในระหว่างการพัฒนา การวิปัสสนาจะช่วยให้เครื่องมือต่างๆ เช่น GraphiQL และ Apollo Studio เข้าใจ API ของคุณ ในการผลิต ให้พิจารณาปิดใช้งานเพื่อซ่อนรายละเอียดการใช้งาน

การตั้งค่านี้ depth-limit ช่วยป้องกันการสืบค้นที่ซ้อนกันที่ซับซ้อนเกินไปซึ่งอาจทําให้ฐานข้อมูลของคุณตึงเครียด ความลึก 8 ช่วยให้สามารถข้ามความสัมพันธ์ได้อย่างสมเหตุสมผลในขณะที่บล็อกการละเมิดที่อาจเกิดขึ้นผ่านการสืบค้นที่ซ้อนกันอย่างลึกซึ้ง

กําหนดการตั้งค่าเอนทิตีเฉพาะ GraphQL

แต่ละเอนทิตีสามารถมีการกําหนดค่าเฉพาะ GraphQL ที่แตกต่างจาก REST:

"Product": {
  "source": { "object": "dbo.Products", "type": "table" },
  "graphql": {
    "enabled": true,
    "type": {
      "singular": "product",
      "plural": "products"
    },
    "operation": "query"
  },
  "rest": {
    "enabled": true
  },
  "permissions": [...]
}

คุณสมบัติจะ type กําหนดชื่อชนิด GraphQL เอง โดยค่าเริ่มต้น DAB จะใช้ชื่อเอนทิตี แต่คุณสามารถระบุรูปแบบเอกพจน์และพหูพจน์ที่แตกต่างกันได้

คุณสมบัติจะ operation กําหนดตําแหน่งที่การกลายพันธุ์ปรากฏ ใช้สําหรับ query เอนทิตีแบบอ่านอย่างเดียว (เช่น มุมมอง) หรือ mutation สําหรับเอนทิตีที่สนับสนุนการดําเนินการเขียน