createDocInBatch method

Future<TurboResponse<WriteBatchWithReference<Map<String, dynamic>>>> createDocInBatch({
  1. required TurboWriteable writeable,
  2. String? id,
  3. WriteBatch? writeBatch,
  4. TurboTimestampType createTimeStampType = TurboTimestampType.createdAtAndUpdatedAt,
  5. TurboTimestampType updateTimeStampType = TurboTimestampType.updatedAt,
  6. bool merge = false,
  7. List<FieldPath>? mergeFields,
  8. String? collectionPathOverride,
})

Creates or writes documents using a batch operation.

This method is similar to createDoc but specifically designed for batch operations, allowing multiple document writes to be atomic.

Parameters:

  • writeable The data to write, must implement TurboWriteable
  • id Optional custom document ID (auto-generated if not provided)
  • writeBatch Optional existing batch to add to (creates new if null)
  • createTimeStampType Type of timestamp to add for new documents
  • updateTimeStampType Type of timestamp to add when merging
  • merge Whether to merge with existing document
  • mergeFields: Specific fields to merge (if merge is true)
  • collectionPathOverride: Optional different collection path

Returns a TurboResponse containing either:

  • Success with WriteBatchWithReference containing the batch and document reference
  • Failure with validation errors or operation errors

Features:

  • Automatic validation through TurboWriteable.validate
  • Timestamp management based on operation type
  • Creates new batch if none provided
  • Merge/upsert capabilities

Example:

final batch = firestore.batch();
final user = User(name: 'John');

final response = await api.createDocInBatch(
  writeable: user,
  writeBatch: batch,
  merge: true,
);

response.when(
  success: (result) async {
    await result.writeBatch.commit();
    print('Created user: ${result.documentReference.id}');
  },
  fail: (error) => print('Error: $error'),
);

Note: The batch must be committed manually after all operations are added.

See also:

Implementation

Future<TurboResponse<WriteBatchWithReference<Map<String, dynamic>>>>
    createDocInBatch({
  required TurboWriteable writeable,
  String? id,
  WriteBatch? writeBatch,
  TurboTimestampType createTimeStampType =
      TurboTimestampType.createdAtAndUpdatedAt,
  TurboTimestampType updateTimeStampType = TurboTimestampType.updatedAt,
  bool merge = false,
  List<FieldPath>? mergeFields,
  String? collectionPathOverride,
}) async {
  assert(
    _isCollectionGroup == (collectionPathOverride != null),
    'Firestore does not support finding a document by id when communicating with a collection group, '
    'therefore, you must specify the collectionPathOverride containing all parent collection and document ids '
    'in order to make this method work.',
  );
  try {
    final TurboResponse<WriteBatchWithReference<Map<String, dynamic>>>?
        invalidResponse = writeable.validate();
    if (invalidResponse != null && invalidResponse.isFail) {
      _log.warning(
        message: 'TurboWriteable was invalid!',
        sensitiveData: null,
      );
      return invalidResponse;
    }
    _log.info(message: 'TurboWriteable is valid!', sensitiveData: null);
    _log.debug(
      message: 'Creating document with batch..',
      sensitiveData: SensitiveData(
        path: collectionPathOverride ?? _collectionPath(),
        id: id,
        isBatch: writeBatch != null,
        createTimeStampType: createTimeStampType,
        updateTimeStampType: updateTimeStampType,
        isMerge: merge,
        mergeFields: mergeFields,
      ),
    );
    final nullSafeWriteBatch = writeBatch ?? this.writeBatch;
    final documentReference = id != null
        ? getDocRefById(
            id: id, collectionPathOverride: collectionPathOverride)
        : _firebaseFirestore
            .collection(collectionPathOverride ?? _collectionPath())
            .doc();
    _log.debug(message: 'Creating JSON..', sensitiveData: null);
    final writeableAsJson = (merge || mergeFields != null) &&
            (await documentReference.get(_getOptions)).exists
        ? updateTimeStampType.add(
            writeable.toJson(),
            updatedAtFieldName: _updatedAtFieldName,
            createdAtFieldName: _createdAtFieldName,
          )
        : createTimeStampType.add(
            writeable.toJson(),
            createdAtFieldName: _createdAtFieldName,
            updatedAtFieldName: _updatedAtFieldName,
          );
    _log.debug(
      message: 'Setting data with writeBatch.set..',
      sensitiveData: SensitiveData(
        path: collectionPathOverride ?? _collectionPath(),
        id: documentReference.id,
        data: writeableAsJson,
      ),
    );
    nullSafeWriteBatch.set(
      documentReference,
      writeableAsJson,
      SetOptions(
        merge: mergeFields == null ? merge : null,
        mergeFields: mergeFields,
      ),
    );
    _log.info(
      message:
          'Adding create to batch done! Returning WriteBatchWithReference..',
      sensitiveData: null,
    );
    return TurboResponse.success(
      result: WriteBatchWithReference(
        writeBatch: nullSafeWriteBatch,
        documentReference: documentReference,
      ),
    );
  } catch (error, stackTrace) {
    _log.error(
      message: 'Unable to create document with batch',
      sensitiveData: SensitiveData(
        path: collectionPathOverride ?? _collectionPath(),
        id: id,
        isBatch: writeBatch != null,
        createTimeStampType: createTimeStampType,
        updateTimeStampType: updateTimeStampType,
        isMerge: merge,
        mergeFields: mergeFields,
      ),
      error: error,
      stackTrace: stackTrace,
    );

    // Convert to TurboFirestoreException and wrap in TurboResponse
    final exception = TurboFirestoreException.fromFirestoreException(
      error,
      stackTrace,
      path: collectionPathOverride ?? _collectionPath(),
      query: 'createDocInBatch(id: $id, merge: $merge)',
    );

    return TurboResponse.fail(error: exception);
  }
}