{}FireSchema

10 structures de base de données Firestore que vous pouvez copier

Modèles de données réels avec exemples JSON Schema complets

Concevoir une base de données Firestore à partir de zéro est difficile. Vous devez penser aux requêtes, à la dénormalisation, aux sous-collections et à une douzaine d'autres préoccupations spécifiques à NoSQL avant d'écrire votre première ligne de code. Au lieu de partir de zéro, utilisez ces 10 modèles éprouvés comme modèles. Chacun représente une architecture d'application courante — e-commerce, chat, SaaS multi-tenant, services basés sur la localisation — avec un JSON Schema complet montrant exactement comment modéliser les collections. Copiez le modèle qui correspond à votre cas d'utilisation, adaptez-le à vos besoins, et vous aurez une base solide en minutes plutôt qu'en semaines.

1. Profils utilisateur

Applications sociales, plateformes SaaS, sites d'adhésion

Collection Structure

firestore_structures.pattern1_structure
schemas/pattern1.schema.jsonJSON
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "collection": "users",
  "description": "User profiles with authentication info",
  "schema": {
    "type": "object",
    "properties": {
      "displayName": {
        "type": "string",
        "description": "User's full name"
      },
      "email": {
        "type": "string",
        "format": "email",
        "description": "Login email address"
      },
      "photoURL": {
        "type": "string",
        "format": "uri",
        "description": "Profile picture URL"
      },
      "role": {
        "type": "string",
        "enum": ["admin", "editor", "viewer"],
        "description": "Access control role"
      },
      "createdAt": {
        "type": "string",
        "format": "date-time",
        "description": "Account creation timestamp"
      }
    },
    "required": ["displayName", "email", "role", "createdAt"]
  }
}

Why this design: Stockez les profils utilisateur comme documents au niveau racine avec l'UID Firebase Auth comme ID de document. Dénormalisez les champs fréquemment consultés comme displayName et photoURL pour qu'ils puissent être intégrés dans d'autres collections sans lectures supplémentaires.

Common mistake: Ne mettez pas les paramètres ou préférences utilisateur en sous-collections sauf s'ils ont des centaines d'éléments. Gardez le document utilisateur léger et rapide à lire.

2. Produits et commandes e-commerce

Boutiques en ligne, marketplaces, systèmes d'inventaire

Collection Structure

firestore_structures.pattern2_structure
schemas/pattern2.schema.jsonJSON
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "collection": "orders",
  "description": "Customer purchase orders",
  "schema": {
    "type": "object",
    "properties": {
      "userId": {
        "type": "string",
        "description": "Reference to users collection"
      },
      "items": {
        "type": "array",
        "description": "Ordered items with denormalized product data",
        "items": {
          "type": "object",
          "properties": {
            "productId": { "type": "string" },
            "name": { "type": "string" },
            "price": { "type": "number", "minimum": 0 },
            "quantity": { "type": "integer", "minimum": 1 }
          },
          "required": ["productId", "name", "price", "quantity"]
        }
      },
      "total": {
        "type": "number",
        "minimum": 0,
        "description": "Order total in USD"
      },
      "status": {
        "type": "string",
        "enum": ["pending", "confirmed", "shipped", "delivered"],
        "description": "Current order status"
      },
      "createdAt": {
        "type": "string",
        "format": "date-time",
        "description": "Order timestamp"
      }
    },
    "required": ["userId", "items", "total", "status", "createdAt"]
  }
}

Why this design: Stockez les commandes comme documents au niveau racine avec userId pour le filtrage. Dénormalisez le nom et le prix du produit dans les articles de commande pour que les commandes historiques restent exactes même si les données produit changent plus tard.

Common mistake: Ne stockez pas les compteurs d'inventaire dans les documents produit — utilisez une collection d'inventaire séparée ou Cloud Functions pour éviter les conditions de concurrence sur les produits populaires.

3. Chat et messagerie

Applications de chat en temps réel, support client, outils de collaboration

Collection Structure

firestore_structures.pattern3_structure
schemas/pattern3.schema.jsonJSON
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "collection": "messages",
  "description": "Chat messages within a room",
  "schema": {
    "type": "object",
    "properties": {
      "authorId": {
        "type": "string",
        "description": "User ID of message author"
      },
      "authorName": {
        "type": "string",
        "description": "Denormalized author display name"
      },
      "text": {
        "type": "string",
        "description": "Message content",
        "maxLength": 5000
      },
      "createdAt": {
        "type": "string",
        "format": "date-time",
        "description": "Message timestamp"
      },
      "edited": {
        "type": "boolean",
        "description": "Whether message was edited"
      }
    },
    "required": ["authorId", "authorName", "text", "createdAt"]
  }
}

Why this design: Utilisez des sous-collections pour les messages afin que chaque salon de chat puisse contenir un nombre illimité de messages. Dénormalisez authorName pour éviter de récupérer les profils utilisateur pour chaque affichage de message. Stockez lastMessage dans le chatRoom parent pour un rendu rapide de l'aperçu.

Common mistake: N'essayez pas d'implémenter les accusés de lecture ou les indicateurs de saisie dans les documents Firestore — utilisez Realtime Database ou Firebase Cloud Messaging pour les données de présence éphémères.

4. Blog avec commentaires

Plateformes de contenu, CMS, forums communautaires

Collection Structure

firestore_structures.pattern4_structure
schemas/pattern4.schema.jsonJSON
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "collection": "posts",
  "description": "Blog posts with metadata",
  "schema": {
    "type": "object",
    "properties": {
      "title": {
        "type": "string",
        "description": "Post title",
        "maxLength": 200
      },
      "content": {
        "type": "string",
        "description": "Post body in markdown"
      },
      "authorId": {
        "type": "string",
        "description": "Reference to users collection"
      },
      "authorName": {
        "type": "string",
        "description": "Denormalized author name"
      },
      "publishedAt": {
        "type": "string",
        "format": "date-time",
        "description": "Publication timestamp"
      },
      "commentCount": {
        "type": "integer",
        "minimum": 0,
        "description": "Cached comment count"
      },
      "tags": {
        "type": "array",
        "items": { "type": "string" },
        "description": "Post tags for filtering"
      }
    },
    "required": ["title", "content", "authorId", "authorName", "publishedAt"]
  }
}

Why this design: Stockez les articles comme documents racine avec des informations d'auteur dénormalisées pour un rendu de liste efficace. Gardez un commentCount mis en cache via Cloud Functions pour éviter de lire toute la sous-collection de commentaires juste pour afficher un compte.

Common mistake: Ne stockez pas la liste complète des commentaires dans le document de l'article sous forme de tableau — cela casse une fois que vous avez plus de quelques dizaines de commentaires et rend la pagination impossible.

5. SaaS multi-tenant

Applications B2B, outils basés sur l'espace de travail, gestion d'équipe

Collection Structure

firestore_structures.pattern5_structure
schemas/pattern5.schema.jsonJSON
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "collection": "organizations",
  "description": "Tenant organizations for multi-tenant SaaS",
  "schema": {
    "type": "object",
    "properties": {
      "name": {
        "type": "string",
        "description": "Organization name"
      },
      "plan": {
        "type": "string",
        "enum": ["free", "pro", "enterprise"],
        "description": "Subscription plan"
      },
      "ownerId": {
        "type": "string",
        "description": "User ID of organization owner"
      },
      "createdAt": {
        "type": "string",
        "format": "date-time",
        "description": "Organization creation timestamp"
      },
      "memberCount": {
        "type": "integer",
        "minimum": 1,
        "description": "Cached member count"
      }
    },
    "required": ["name", "plan", "ownerId", "createdAt"]
  }
}

Why this design: Utilisez les organisations comme collection de niveau supérieur avec toutes les données tenant imbriquées en dessous. Cela simplifie les règles de sécurité : les utilisateurs ne peuvent accéder qu'aux données au sein de leur organisation. Stockez les rôles de membre dans une sous-collection pour une énumération facile.

Common mistake: Ne dupliquez pas les données d'organisation dans les documents utilisateur — cela crée des problèmes de synchronisation. Au lieu de cela, interrogez la collection organizations filtrée par appartenance utilisateur.

6. Journal d'activité et d'audit

Suivi de conformité, flux d'activité utilisateur, tableaux de bord admin

Collection Structure

firestore_structures.pattern6_structure
schemas/pattern6.schema.jsonJSON
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "collection": "activityLog",
  "description": "Audit trail of user actions",
  "schema": {
    "type": "object",
    "properties": {
      "userId": {
        "type": "string",
        "description": "User who performed the action"
      },
      "userName": {
        "type": "string",
        "description": "Denormalized user name"
      },
      "action": {
        "type": "string",
        "enum": ["created", "updated", "deleted", "viewed"],
        "description": "Action type"
      },
      "resourceType": {
        "type": "string",
        "description": "Type of resource affected (e.g., 'post', 'user')"
      },
      "resourceId": {
        "type": "string",
        "description": "ID of affected resource"
      },
      "metadata": {
        "type": "object",
        "description": "Additional context data"
      },
      "timestamp": {
        "type": "string",
        "format": "date-time",
        "description": "When the action occurred"
      }
    },
    "required": ["userId", "action", "resourceType", "resourceId", "timestamp"]
  }
}

Why this design: Stockez les journaux d'activité comme collection racine avec des champs indexés pour userId, action et timestamp. Générez des entrées de journal via Cloud Functions sur les écritures de documents pour garantir des pistes d'audit complètes même si le code client échoue.

Common mistake: N'essayez pas de stocker les journaux comme sous-collections sous les utilisateurs ou les ressources — cela rend les requêtes inter-utilisateurs ou inter-ressources impossibles. Utilisez une collection plate avec des champs de référence.

7. Géolocalisation et cartes

Services basés sur la localisation, applications de livraison, localisateurs de magasins

Collection Structure

firestore_structures.pattern7_structure
schemas/pattern7.schema.jsonJSON
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "collection": "locations",
  "description": "Locations with geospatial data",
  "schema": {
    "type": "object",
    "properties": {
      "name": {
        "type": "string",
        "description": "Location name"
      },
      "address": {
        "type": "string",
        "description": "Street address"
      },
      "geopoint": {
        "type": "object",
        "description": "Firestore GeoPoint",
        "properties": {
          "latitude": { "type": "number", "minimum": -90, "maximum": 90 },
          "longitude": { "type": "number", "minimum": -180, "maximum": 180 }
        },
        "required": ["latitude", "longitude"]
      },
      "geohash": {
        "type": "string",
        "description": "Geohash for proximity queries"
      },
      "category": {
        "type": "string",
        "enum": ["restaurant", "store", "office", "other"],
        "description": "Location type"
      }
    },
    "required": ["name", "geopoint", "geohash"]
  }
}

Why this design: Stockez des chaînes geohash à côté des champs GeoPoint pour permettre des requêtes de proximité efficaces. Firestore ne peut pas faire de recherches de rayon natives, donc geohash vous permet de filtrer par préfixe pour trouver des emplacements à proximité. Utilisez des bibliothèques comme geofire-common pour générer des hashes.

Common mistake: N'essayez pas d'interroger par plages latitude/longitude directement — Firestore ne peut pas faire de requêtes d'inégalité composées. Utilisez toujours des préfixes geohash pour le filtrage basé sur la localisation.

8. Gestion des stocks

Systèmes d'entrepôt, suivi des stocks, applications de chaîne d'approvisionnement

Collection Structure

firestore_structures.pattern8_structure
schemas/pattern8.schema.jsonJSON
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "collection": "inventory",
  "description": "Inventory items with stock levels",
  "schema": {
    "type": "object",
    "properties": {
      "sku": {
        "type": "string",
        "description": "Stock keeping unit code"
      },
      "name": {
        "type": "string",
        "description": "Item name"
      },
      "quantity": {
        "type": "integer",
        "minimum": 0,
        "description": "Current stock quantity"
      },
      "warehouseId": {
        "type": "string",
        "description": "Warehouse location reference"
      },
      "reorderLevel": {
        "type": "integer",
        "minimum": 0,
        "description": "Quantity threshold for reorder alerts"
      },
      "lastRestocked": {
        "type": "string",
        "format": "date-time",
        "description": "Last restock timestamp"
      }
    },
    "required": ["sku", "name", "quantity", "warehouseId"]
  }
}

Why this design: Utilisez des transactions lors de la mise à jour de la quantité pour éviter les conditions de concurrence. Pour un inventaire à volume élevé avec des mises à jour fréquentes, envisagez d'utiliser des compteurs distribués ou une collection de journal de transactions séparée pour éviter la contention d'écriture.

Common mistake: N'incrémentez/décrémentez pas les champs de quantité depuis le code client sans transactions — vous obtiendrez des comptages incorrects sous accès concurrent. Utilisez Cloud Functions ou une logique côté serveur.

9. Fil social et abonnés

Réseaux sociaux, fils d'actualités, flux d'activité

Collection Structure

firestore_structures.pattern9_structure
schemas/pattern9.schema.jsonJSON
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "collection": "posts",
  "description": "Social feed posts",
  "schema": {
    "type": "object",
    "properties": {
      "authorId": {
        "type": "string",
        "description": "User ID of post author"
      },
      "authorName": {
        "type": "string",
        "description": "Denormalized author display name"
      },
      "content": {
        "type": "string",
        "description": "Post content",
        "maxLength": 5000
      },
      "likeCount": {
        "type": "integer",
        "minimum": 0,
        "description": "Cached like count"
      },
      "createdAt": {
        "type": "string",
        "format": "date-time",
        "description": "Post timestamp"
      }
    },
    "required": ["authorId", "authorName", "content", "createdAt"]
  }
}

Why this design: Stockez les abonnés et les abonnements comme sous-collections séparées sous chaque utilisateur pour permettre des requêtes efficaces dans les deux directions. Gardez un likeCount mis en cache sur les articles mis à jour via Cloud Functions au lieu de lire toute la sous-collection likes.

Common mistake: Ne diffusez pas les articles à tous les fils d'abonnés lors de l'écriture — cela ne passe pas à l'échelle. Au lieu de cela, interrogez les articles des utilisateurs suivis en temps réel en utilisant une requête array-contains sur les ID d'abonnement.

10. IoT et données de capteurs

Tableaux de bord IoT, surveillance environnementale, télémétrie d'appareils

Collection Structure

firestore_structures.pattern10_structure
schemas/pattern10.schema.jsonJSON
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "collection": "readings",
  "description": "Sensor readings from IoT devices",
  "schema": {
    "type": "object",
    "properties": {
      "temperature": {
        "type": "number",
        "description": "Temperature in Celsius"
      },
      "humidity": {
        "type": "number",
        "minimum": 0,
        "maximum": 100,
        "description": "Relative humidity percentage"
      },
      "batteryLevel": {
        "type": "number",
        "minimum": 0,
        "maximum": 100,
        "description": "Battery percentage"
      },
      "timestamp": {
        "type": "string",
        "format": "date-time",
        "description": "Reading timestamp"
      }
    },
    "required": ["timestamp"]
  }
}

Why this design: Stockez les données de séries temporelles comme sous-collections sous chaque appareil. Pour les données haute fréquence, groupez les écritures et implémentez un nettoyage TTL via Cloud Functions pour éviter une croissance illimitée. Envisagez les politiques TTL Cloud Firestore ou les exportations BigQuery pour les analyses à long terme.

Common mistake: Ne stockez pas chaque lecture de capteur si votre appareil rapporte chaque seconde — vous dépasserez les limites d'écriture et les coûts de Firestore. Agrégez en intervalles de minutes ou d'heures, ou utilisez Realtime Database pour les écritures haute fréquence.

Transformez ces modèles en documentation

Ces JSON Schemas ne sont pas que des exemples — ce sont des documentations fonctionnelles que vous pouvez utiliser dans votre projet. Enregistrez-les comme fichiers .schema.json dans votre dépôt, rendez-les avec FireSchema, et donnez à votre équipe une référence navigable qu'elle utilisera réellement. Cela prend 5 minutes à configurer.

Prochaines étapes

Maintenant que vous avez des modèles avec lesquels travailler, apprenez à les utiliser efficacement :

Essayer FireSchema

Guide de démarrage rapide