GraphQL توسعه‌دهنده API را قادر می‌سازد تا داده‌های برنامه را به‌عنوان یک نمودار مدل کند، و کلاینت‌های API که از آن داده‌ها درخواست می‌کنند تا به راحتی از این نمودار داده عبور کنند تا آن را بازیابی کنند. اینها قابلیت های قدرتمندی برای تغییر بازی هستند. اما اگر باطن شما آماده گراف نباشد، این قابلیت‌ها می‌توانند با اعمال فشار بیشتر بر پایگاه داده‌تان به بدهی تبدیل شوند و زمان و منابع بیشتری را مصرف کنند.

در این مقاله، روش‌هایی را بیان می‌کنم که می‌توانید با استفاده از یک پایگاه داده گراف به عنوان پشتیبان برای GraphQL API بعدی خود، با بهره‌گیری از قابلیت‌های ارائه‌شده توسط منبع باز، این مشکلات را کاهش دهید. کتابخانه Neo4j GraphQL.

نمودارها چیست و چرا به پایگاه داده نیاز دارند

اساساً، یک نمودار یک ساختار داده است که از گره ها (موجودات موجود در مدل داده) به همراه روابط بین گره ها تشکیل شده است. نمودارها همه در مورد اتصالات موجود در داده های شما هستند. به همین دلیل، روابط در مدل داده های گراف، شهروندان درجه یک هستند.

تجسم روابط بین گره ها در یک گراف
(پیش نمایش بزرگ)

نمودارها به قدری مهم هستند که یک دسته کامل از پایگاه های داده برای کار با نمودارها ایجاد شد: پایگاه های داده گراف. بر خلاف پایگاه داده های رابطه ای یا اسنادی که به ترتیب از جداول یا اسناد به عنوان مدل داده های خود استفاده می کنند، مدل داده پایگاه داده گراف (حدس زدید!) یک نمودار است.

نمونه هایی از پایگاه داده های رابطه ای، اسنادی و نموداری
(پیش نمایش بزرگ)

GraphQL به عنوان یک زبان پرس و جو پایگاه داده نیست و هرگز قرار نبوده است. این در واقع یک زبان پرس و جو است، اما فاقد بسیاری از معنایی است که ما از یک زبان جستجوی پایگاه داده واقعی مانند SQL یا Cypher انتظار داریم. این از عمد است. شما نمی خواهید کل پایگاه داده ما را در معرض همه برنامه های مشتری خود در سراسر جهان قرار دهید.

در عوض، GraphQL یک زبان پرس و جوی API برای مدل سازی است داده های برنامه به عنوان یک گراف و برای نمایش و پرس و جوی آن نمودار داده، دقیقاً همانطور که SQL و Cypher به ترتیب برای کار با پایگاه‌های داده رابطه‌ای و نموداری به‌طور هدفمند ساخته شدند. از آنجایی که یکی از عملکردهای اصلی یک برنامه API تعامل با پایگاه داده است، منطقی است که ادغام پایگاه داده GraphQL باید به ساخت API های GraphQL که توسط یک پایگاه داده پشتیبانی می شوند کمک کند. این دقیقاً همان کاری است که کتابخانه Neo4j GraphQL انجام می دهد – ساخت API های GraphQL با پشتیبانی Neo4j را آسان تر می کند.

یکی از قدرتمندترین قابلیت‌های GraphQL، طراح API را قادر می‌سازد تا با استفاده از گره‌ها و روابط، کل دامنه داده را به صورت یک نمودار بیان کند. به این ترتیب، مشتریان API می توانند نمودار داده را برای یافتن داده های مربوطه طی کنند. این منطق بهتری دارد زیرا بیشتر تعاملات API در زمینه روابط انجام می شود. به عنوان مثال، اگر می‌خواهیم تمام سفارش‌های ارسال شده توسط یک مشتری خاص یا همه محصولات را در یک سفارش مشخص واکشی کنیم، در حال عبور از الگوی روابط هستیم تا آن اتصالات را در داده‌های خود پیدا کنیم.

بلافاصله پس از اینکه GraphQL در سال 2015 توسط فیس بوک منبع باز شد، مجموعه ای از ادغام های پایگاه داده GraphQL ظاهر شد، ظاهراً در تلاش برای رسیدگی به مشکلات n+1 معما و مشکلات مشابه Neo4j GraphQL Library یکی از این ادغام ها بود.

تجسم ارتباط بین GraphQL Client، GraphQL API و Neo4j
(پیش نمایش بزرگ)

مشکلات رایج پیاده سازی GraphQL

ساخت یک سرویس GraphQL API مستلزم انجام دو مرحله است:

  1. طرحواره را تعریف کنید و تعاریف را تایپ کنید.
  2. توابع حل‌کننده را برای هر نوع و فیلد در طرح ایجاد کنید که مسئول واکشی یا به‌روزرسانی داده‌ها در لایه داده ما خواهد بود.

ترکیب این توابع طرحواره و حل‌کننده، یک شی طرح اجرایی GraphQL را به شما می‌دهد. سپس می‌توانید شی schema را به یک لایه شبکه، مانند یک وب سرور Node.js یا تابع lambda، متصل کنید تا GraphQL API را در معرض دید مشتریان قرار دهید. اغلب توسعه‌دهندگان از ابزارهایی مانند Apollo Server یا GraphQL Yoga برای کمک به این فرآیند استفاده می‌کنند، اما انجام دو مرحله اول هنوز به عهده آنهاست.

اگر تا به حال توابع حل‌کننده را نوشته‌اید، به‌خاطر می‌آورید که ممکن است کمی خسته‌کننده باشند، زیرا معمولاً با کد واکشی داده‌های دیگ بخار پر می‌شوند. اما حتی بدتر از از دست دادن بهره وری توسعه دهندگان است مخوف n+1 مشکل پرس و جو. به دلیل روش تو در تو که توابع حل‌کننده GraphQL فراخوانی می‌شوند، یک درخواست GraphQL می‌تواند منجر به درخواست‌های رفت و برگشت متعدد به پایگاه داده شود. پرداختن به این مورد معمولاً مستلزم استراتژی دسته‌بندی و ذخیره‌سازی است که پیچیدگی بیشتری را به برنامه GraphQL شما اضافه می‌کند.

دوبرابر کردن توسعه GraphQL-First

در اصل، اصطلاح GraphQL-First Development یک فرآیند مشارکتی را توصیف کرد. تیم‌های Frontend و Backend بر روی یک طرح GraphQL به توافق می‌رسند، سپس به طور مستقل مشغول ساختن قطعات مربوطه خود از پایگاه کد می‌شوند. ادغام پایگاه داده ایده توسعه GraphQL-First را با اعمال این مفهوم در پایگاه داده نیز گسترش می دهد. تعاریف نوع GraphQL اکنون می توانند پایگاه داده را هدایت کنند.

می توانید نمونه کدهای کامل ارائه شده در اینجا را بیابید GitHub.

فرض کنید شما در حال ساختن یک برنامه بررسی کسب و کار هستید که می خواهید کسب و کارها، کاربران و نظرات کاربران را ردیابی کنید. تعاریف نوع GraphQL برای توصیف این API ممکن است چیزی شبیه به این باشد:

type Business {
  businessId: ID!
  name: String!
  city: String!
  state: String!
  address: String!
  location: Point!
  reviews: [Review!]! @relationship(type: "REVIEWS", direction: IN)
  categories: [Category!]!
    @relationship(type: "IN_CATEGORY", direction: OUT)
}

type User {
  userID: ID!
  name: String!
  reviews: [Review!]! @relationship(type: "WROTE", direction: OUT)
}

type Review {
  reviewId: ID!
  stars: Float!
  date: Date!
  text: String
  user: User! @relationship(type: "WROTE", direction: IN)
  business: Business! @relationship(type: "REVIEWS", direction: OUT)
}

type Category {
  name: String!
  businesses: [Business!]!
    @relationship(type: "IN_CATEGORY", direction: IN)
}

به استفاده از دستورالعمل طرحواره GraphQL توجه کنید @relationship در تعاریف نوع ما دستورالعمل های طرحواره GraphQL مکانیزم داخلی داخلی زبان و اجزای کلیدی برای گسترش و پیکربندی GraphQL APIها هستند – به ویژه با ادغام پایگاه داده مانند Neo4j GraphQL Library. در این مورد، @relationship دستورالعمل نوع رابطه و جهت (داخل یا خارج) را برای جفت گره ها در پایگاه داده کد می کند.

سپس از تعاریف نوع برای تعریف مدل داده های نمودار ویژگی در Neo4j استفاده می شود. به جای حفظ دو طرحواره (یکی برای پایگاه داده ما و دیگری برای API ما)، اکنون می توانید از تعاریف نوع برای تعریف API و مدل داده پایگاه داده استفاده کنید. علاوه بر این، از آنجایی که Neo4j طرحی اختیاری است، استفاده از GraphQL برای هدایت پایگاه داده، لایه ای از نوع ایمنی را به برنامه شما اضافه می کند.

مدل داده های نمودار ویژگی در Neo4j
(پیش نمایش بزرگ)

از تعاریف نوع GraphQL تا طرحواره های API کامل

در GraphQL، شما از فیلدهای مربوط به انواع خاص (Query، Mutation و Subscription) برای تعریف نقاط ورودی برای API استفاده می کنید. علاوه بر این، ممکن است بخواهید آرگومان های فیلدی را تعریف کنید که می توانند در زمان پرس و جو ارسال شوند، به عنوان مثال، برای مرتب سازی یا فیلتر کردن. کتابخانه Neo4j GraphQL با ایجاد نقاط ورودی در GraphQL API برای انجام این کار create، read، update، و delete عملیات برای هر نوع، و همچنین آرگومان های فیلد برای مرتب سازی و فیلتر کردن.

بیایید به چند نمونه نگاه کنیم. برای برنامه بررسی کسب و کار ما، فرض کنید می‌خواهید فهرستی از کسب‌وکارها را نشان دهید که بر اساس حروف الفبا مرتب شده‌اند. کتابخانه Neo4j GraphQL به طور خودکار آرگومان های فیلد را برای انجام این کار اضافه می کند.

{
  businesses(options: { limit: 10, sort: { name: ASC } }) {
    name
  }
}

شاید بخواهید به کاربران اجازه دهید تا با جستجوی شرکت ها بر اساس نام یا کلمه کلیدی، این لیست از مشاغل را فیلتر کنند. را where بحث و جدل این نوع فیلتر را مدیریت می کند:

{
  businesses(where: { name_CONTAINS: "Brew" }) {
    name
    address
  }

سپس می توانید این آرگومان های فیلتر را برای بیان عملیات بسیار پیچیده ترکیب کنید. مثلاً می‌خواهید کسب‌وکارهایی را پیدا کنید که در دسته قهوه یا صبحانه هستند و نظرات حاوی کلمه کلیدی «ساندویچ صبحانه»:

{
  businesses(
    where: {
      OR: [
        { categories_SOME: { name: "Coffee" } }
        { categories_SOME: { name: "Breakfast" } }
      ]
    }
  ) {
    name
    address
    reviews(where: { text_CONTAINS: "breakfast sandwich" }) {
    stars
    text
  }
 }
}

برای مثال، با استفاده از داده‌های مکان، حتی می‌توانید کسب‌وکارهایی را در 1 کیلومتری مکان فعلی‌مان جستجو کنید:

{
  businesses(
    where: {
      location_LT: {
        distance: 1000
        point: { latitude: 37.563675, longitude: -122.322243 }
      }
    }
  ) {
  name
  address
  city
  state
  }
}

همانطور که می بینید، این عملکرد بسیار قدرتمند است و API تولید شده را می توان با استفاده از دستورالعمل های طرحواره GraphQL پیکربندی کرد.

ما به حل کننده های بدبو نیاز نداریم

همانطور که قبلاً اشاره کردیم، پیاده سازی سرور GraphQL به توابع حل کننده نیاز دارد که در آن منطق تعامل با لایه داده وجود دارد. با ادغام های پایگاه داده مانند Neo4j GraphQL Library، در زمان پرس و جو برای شما برای ترجمه درخواست های GraphQL دلخواه به پرس و جوهای پایگاه داده محصور شده و تکی، حل کننده ها برای شما ایجاد می شوند. این یک پیروزی بزرگ در بهره‌وری توسعه‌دهندگان است (نیازی نیست کد واکشی داده‌های دیگ بخاری را بنویسیم – بله!). همچنین به آن می پردازد n+1 مشکل پرس و جو با ایجاد یک درخواست رفت و برگشت واحد به پایگاه داده.

علاوه بر این، پایگاه‌های داده گراف مانند Neo4j دقیقاً برای نوع پیمایش داده‌های گراف تودرتو که معمولاً در GraphQL بیان می‌شوند، بهینه‌سازی شده‌اند. بیایید این را در عمل ببینیم. هنگامی که تعاریف نوع GraphQL خود را تعریف کردید، در اینجا تمام کدهای لازم برای چرخش API کاملاً کاربردی GraphQL شما وجود دارد:

const { ApolloServer } = require("apollo-server");
const neo4j = require("neo4j-driver");
const { Neo4jGraphQL } = require("@neo4j/graphql");

// Connect to your Neo4j instance.
const driver = neo4j.driver(
  "neo4j+s://my-neo4j-db.com",
  neo4j.auth.basic("neo4j", "letmein")
);

// Pass our GraphQL type definitions and Neo4j driver instance.
const neoSchema = new Neo4jGraphQL({ typeDefs, driver });

// Generate an executable GraphQL schema object and start
// Apollo Server.
neoSchema.getSchema().then((schema) => {
  const server = new ApolloServer({
    schema,
  });
  server.listen().then(({ url }) => {
    console.log(`GraphQL server ready at ${url}`);
  });
});

خودشه! هیچ حل کننده ای وجود ندارد.

GraphQL را با قدرت Cypher گسترش دهید

تا اینجا ما فقط در مورد پایه صحبت کردیم create، read، update، و delete عملیات چگونه می توانید منطق سفارشی را با Neo4j GraphQL Library مدیریت کنید؟

فرض کنید می‌خواهید کسب‌وکارهای توصیه‌شده را بر اساس سابقه جستجو یا بررسی به کاربران خود نشان دهید. یکی از راه‌ها این است که تابع حل‌کننده خود را با منطق ایجاد آن توصیه‌های شخصی‌سازی شده پیاده‌سازی کنید. با این حال، راه بهتری برای حفظ ضمانت عملکرد یک به یک، GraphQL به پایگاه داده وجود دارد: می‌توانید از قدرت استفاده کنید. زبان پرس و جو Cypher با استفاده از @cypher دستورالعمل طرحواره GraphQL تا منطق سفارشی خود را در تعاریف نوع GraphQL خود تعریف کنید.

Cypher یک زبان فوق العاده قدرتمند است که شما را قادر می سازد تا الگوهای گراف پیچیده را با استفاده از نحو اعلانی هنر مانند ASCII بیان کنید. من در این مقاله به جزئیات Cypher نمی پردازم، اما بیایید ببینیم چگونه می توانید وظیفه توصیه شخصی ما را با افزودن یک فیلد جدید به تعاریف نوع GraphQL خود انجام دهید:

extend type Business {
  recommended(first: Int = 1): [Business!]!
    @cypher(
      statement: """
        MATCH (this)<-[:REVIEWS]-(:Review)<-[:WROTE]-(u:User)
        MATCH (u)-[:WROTE]->(:Review)-[:REVIEWS]->(rec:Business)
        WITH rec, COUNT(*) AS score
        RETURN rec ORDER BY score DESC LIMIT $first
      """
    )
}

اینجا کسب و کار نوع دارای الف است توصیه شده فیلد، که از پرس و جوی Cypher تعریف شده در بالا برای نشان دادن مشاغل توصیه شده در زمان درخواست GraphQL استفاده می کند. برای انجام این کار نیازی به نوشتن یک حل کننده سفارشی ندارید. کتابخانه Neo4j GraphQL هنوز هم می تواند یک درخواست پایگاه داده واحد را حتی در صورت استفاده از یک سفارشی ایجاد کند توصیه شده رشته.

ادغام پایگاه داده GraphQL Under The Hood

ادغام های پایگاه داده GraphQL مانند Neo4j GraphQL Library توسط GraphQLResolveInfo هدف – شی. این شی به همه حل‌کننده‌ها، از جمله مواردی که توسط Neo4j GraphQL Library برای ما تولید شده‌اند، ارسال می‌شود. این شامل اطلاعاتی در مورد طرحواره GraphQL و عملیات GraphQL است که حل می شود. با بازرسی دقیق این شی، ادغام های پایگاه داده GraphQL می توانند پرس و جوهای پایگاه داده را در زمان قرارگیری کوئری ها ایجاد کنند.

تجسم شی GraphQLResolveInfo
(پیش نمایش بزرگ)

اگر علاقه دارید، من اخیراً در GraphQL Summit سخنرانی کردم که به جزئیات بسیار بیشتری می رود.

یک کتابخانه منبع باز که با هر پیاده سازی جاوا اسکریپت GraphQL کار می کند، به طور قابل تصوری می تواند یک اکوسیستم کامل از ابزارهای GraphQL با کد پایین را تامین کند. در مجموع، این ابزارها از عملکرد کتابخانه Neo4j GraphQL استفاده می‌کنند تا ساخت، آزمایش و استقرار APIهای GraphQL با پشتیبانی یک پایگاه داده واقعی گراف را برای شما آسان‌تر کنند.

مثلا، GraphQL Mesh از Neo4j GraphQL Library برای فعال کردن Neo4j به عنوان منبع داده برای فدراسیون داده ها استفاده می کند. آیا نمی خواهید کد لازم برای ساخت یک GraphQL API برای آزمایش و توسعه را بنویسید؟ را جعبه ابزار Neo4j GraphQL یک رابط وب منبع باز و کم کد است که Neo4j GraphQL Library را در بر می گیرد. به این ترتیب، می تواند یک GraphQL API را از پایگاه داده Neo4j موجود با یک کلیک ایجاد کند.

اسکرین شات جعبه ابزار Neo4j GraphQL
(پیش نمایش بزرگ)

کجا از اینجا

اگر ساختن یک GraphQL API با پشتوانه یک پایگاه داده گراف بومی برای مشکلاتی که به عنوان یک توسعه‌دهنده می‌خواهید حل کنید جالب یا اصلا مفید به نظر می‌رسد، من شما را تشویق می‌کنم کتابخانه Neo4j GraphQL را امتحان کنید. همچنین صفحه فرود کتابخانه Neo4j GraphQL نقطه شروع خوبی برای مستندسازی، مثال‌های بیشتر و کارگاه‌های جامع است.

یک کتاب هم نوشته ام برنامه های Full Stack GraphQLمنتشر شده توسط منینگ، که این موضوع را با عمق بیشتری پوشش می دهد. کتاب من مدیریت مجوز، کار با برنامه frontend و استفاده از سرویس‌های ابری مانند Auth0، Netlify، AWS Lambda، و Neo4j Aura را برای استقرار یک برنامه GraphQL تمام پشته پوشش می‌دهد. در واقع، من از این مقاله به عنوان مثال در کتاب، برنامه بررسی های تجاری را ایجاد کرده ام! به لطف Neo4j، این کتاب اکنون به عنوان یک در دسترس است دانلود رایگان.

آخرین اما نه کم‌اهمیت‌ترین، من یک جلسه زنده با عنوان «ایجاد حس داده‌های مکانی با نمودارهای دانش» در کنفرانس مجازی NODES 2022 در چهارشنبه، 16 نوامبر، تولید شده توسط Neo4j ارائه خواهم کرد. ثبت نام برای تمامی شرکت کنندگان رایگان است.

سرمقاله Smashing
(yk, il)