🌐 Detecting your location…
📢 Advertisement — Configure AdSense in Appearance → Customize → AdSense Settings

গ্রাফকিউএল সম্পূর্ণ গাইড 2026: স্কিমা, প্রশ্ন, মিউটেশন এবং প্রতিক্রিয়া

⏱️4 min read  ·  738 words

GraphQL হল API ক্যোয়ারী ল্যাঙ্গুয়েজ যা ক্লায়েন্টদের তাদের প্রয়োজনীয় ডেটার অনুরোধ করতে দেয়। 2026 সালে, গ্রাফকিউএল Facebook, GitHub, Shopify, Twitter এবং হাজার হাজার স্টার্টআপ দ্বারা ব্যবহৃত হয়। এই নির্দেশিকাটি GraphQL স্কিমা ডিজাইন, প্রশ্ন, মিউটেশন, সাবস্ক্রিপশন এবং প্রোডাকশন প্যাটার্ন কভার করে।

গ্রাফকিউএল বনাম REST

দৃষ্টিভঙ্গি বিশ্রাম গ্রাফকিউএল
ডেটা আনা হচ্ছে একাধিক শেষ পয়েন্ট, স্থির প্রতিক্রিয়া একক শেষ বিন্দু, নমনীয় প্রতিক্রিয়া
ওভার-ফেচিং সাধারণ সমস্যা নির্মূল — আপনার যা প্রয়োজন ঠিক তা পান
আন্ডার-ফেচিং একাধিক অনুরোধ প্রয়োজন নেস্টেড ডেটার জন্য একটি অনুরোধ
টাইপ নিরাপত্তা OpenAPI (ঐচ্ছিক) অন্তর্নির্মিত শক্তিশালী টাইপিং
শেখার বক্ররেখা Low মাঝারি
জন্য সেরা সাধারণ CRUD APIs জটিল, আন্তঃসংযুক্ত ডেটা

গ্রাফকিউএল স্কিমা

# Schema Definition Language (SDL)
type Query {
  user(id: ID!): User
  users(first: Int, after: String): UserConnection!
  post(id: ID!): Post
  posts(filter: PostFilter, orderBy: PostOrderBy): [Post!]!
  me: User
}

type Mutation {
  createUser(input: CreateUserInput!): CreateUserPayload!
  updateUser(id: ID!, input: UpdateUserInput!): User!
  deleteUser(id: ID!): Boolean!
  createPost(input: CreatePostInput!): Post!
}

type Subscription {
  userCreated: User!
  postPublished: Post!
}

type User {
  id: ID!
  name: String!
  email: String!
  posts(first: Int): [Post!]!
  createdAt: DateTime!
}

type Post {
  id: ID!
  title: String!
  content: String!
  author: User!
  tags: [String!]!
  published: Boolean!
  publishedAt: DateTime
}

input CreateUserInput {
  name: String!
  email: String!
  password: String!
}

type CreateUserPayload {
  user: User!
  token: String!
}

type UserConnection {
  edges: [UserEdge!]!
  pageInfo: PageInfo!
  totalCount: Int!
}

type UserEdge {
  node: User!
  cursor: String!
}

type PageInfo {
  hasNextPage: Boolean!
  endCursor: String
}

scalar DateTime

প্রশ্ন এবং মিউটেশন

# Basic query
query GetUser {
  user(id: "1") {
    id
    name
    email
    posts(first: 5) {
      title
      publishedAt
    }
  }
}

# Query with variables (best practice)
query GetUserPosts($userId: ID!, $first: Int = 10) {
  user(id: $userId) {
    name
    posts(first: $first) {
      id
      title
      tags
      author {
        name
      }
    }
  }
}

# Mutation
mutation CreatePost($input: CreatePostInput!) {
  createPost(input: $input) {
    id
    title
    author {
      name
    }
    publishedAt
  }
}

# Variables JSON:
# {
#   "input": {
#     "title": "TypeScript Guide 2026",
#     "content": "...",
#     "tags": ["typescript", "javascript"]
#   }
# }

# Fragments — reuse field selections
fragment UserFields on User {
  id
  name
  email
}

query {
  user(id: "1") { ...UserFields }
  me { ...UserFields }
}

পাইথন (স্ট্রবেরি) সহ গ্রাফকিউএল

pip install strawberry-graphql fastapi uvicorn

import strawberry
from strawberry.fastapi import GraphQLRouter
from fastapi import FastAPI
from typing import Optional
import asyncio

@strawberry.type
class User:
    id: strawberry.ID
    name: str
    email: str

@strawberry.type
class Post:
    id: strawberry.ID
    title: str
    content: str
    author: User

@strawberry.input
class CreatePostInput:
    title: str
    content: str
    tags: list[str] = strawberry.field(default_factory=list)

@strawberry.type
class Query:
    @strawberry.field
    async def user(self, id: strawberry.ID) -> Optional[User]:
        # Fetch from database
        user_data = await db.users.find_one({"id": id})
        if not user_data:
            return None
        return User(id=user_data["id"], name=user_data["name"], email=user_data["email"])

    @strawberry.field
    async def posts(self, first: int = 10) -> list[Post]:
        posts_data = await db.posts.find().limit(first).to_list(first)
        return [Post(id=p["id"], title=p["title"], content=p["content"],
                     author=User(id=p["author_id"], name=p["author_name"], email=""))
                for p in posts_data]

@strawberry.type
class Mutation:
    @strawberry.mutation
    async def create_post(self, input: CreatePostInput) -> Post:
        new_post = {"title": input.title, "content": input.content, "tags": input.tags}
        result = await db.posts.insert_one(new_post)
        return Post(id=str(result.inserted_id), title=input.title, content=input.content,
                    author=User(id="1", name="Alice", email="alice@example.com"))

schema = strawberry.Schema(query=Query, mutation=Mutation)
graphql_app = GraphQLRouter(schema)

app = FastAPI()
app.include_router(graphql_app, prefix="/graphql")
# Playground at http://localhost:8000/graphql

N+1 সমস্যা এবং ডেটালোডার

N+1 সমস্যা: পোস্টের একটি তালিকা আনা, তারপর লেখকের জন্য 1 DB ক্যোয়ারী তৈরি করা = N+1 মোট প্রশ্ন।

from strawberry.dataloader import DataLoader

async def load_users_by_ids(user_ids: list[str]) -> list[User]:
    # ONE query for all user IDs
    users_data = await db.users.find({"id": {"$in": user_ids}}).to_list(None)
    user_map = {u["id"]: u for u in users_data}
    return [user_map.get(uid) for uid in user_ids]

# In your GraphQL context
context = {
    "user_loader": DataLoader(load_fn=load_users_by_ids)
}

# In resolver — batches all user lookups into one query
@strawberry.type
class Post:
    author_id: strawberry.Private[str]

    @strawberry.field
    async def author(self, info: strawberry.types.Info) -> User:
        return await info.context["user_loader"].load(self.author_id)

অ্যাপোলো ক্লায়েন্ট (প্রতিক্রিয়া)

// Setup
import { ApolloClient, InMemoryCache, ApolloProvider, gql, useQuery, useMutation } from '@apollo/client';

const client = new ApolloClient({
  uri: 'https://api.example.com/graphql',
  cache: new InMemoryCache(),
});

// Wrap app
function App() {
  return <ApolloProvider client={client}><Router /></ApolloProvider>;
}

// Query hook
const GET_POSTS = gql`
  query GetPosts($first: Int!) {
    posts(first: $first) {
      id title author { name }
    }
  }
`;

function PostList() {
  const { data, loading, error } = useQuery(GET_POSTS, {
    variables: { first: 10 },
    fetchPolicy: 'cache-and-network',
  });

  if (loading) return <Spinner />;
  if (error) return <Error message={error.message} />;

  return (
    <ul>
      {data.posts.map(post => (
        <li key={post.id}>{post.title} by {post.author.name}</li>
      ))}
    </ul>
  );
}

// Mutation hook
const CREATE_POST = gql`
  mutation CreatePost($input: CreatePostInput!) {
    createPost(input: $input) { id title }
  }
`;

function NewPostForm() {
  const [createPost, { loading }] = useMutation(CREATE_POST, {
    update(cache, { data: { createPost } }) {
      // Update cache to include new post
      cache.modify({
        fields: {
          posts(existingPosts = []) {
            return [...existingPosts, createPost];
          }
        }
      });
    }
  });

  const handleSubmit = (title: string) => {
    createPost({ variables: { input: { title, content: '' } } });
  };
}

2026 সালে গ্রাফকিউএল পরিপক্ক এবং উৎপাদনের জন্য প্রস্তুত। যখন আপনার ফ্রন্টএন্ড নমনীয় ডেটা আনার প্রয়োজন হয়, যখন মোবাইল এবং ওয়েব ক্লায়েন্টদের বিভিন্ন ডেটা আকারের প্রয়োজন হয়, বা যখন আপনার আন্তঃসংযুক্ত ডেটা (ব্যবহারকারী/পোস্ট/মন্তব্য) থাকে তখন এটি ব্যবহার করুন। সাধারণ CRUD API-এর জন্য REST ব্যবহার করুন বা যখন ক্লায়েন্টরা কোন ডেটা পাবে তা নিয়ন্ত্রণ করে না।

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা