kevlened / fireway

A schema migration tool for firestore
MIT License
279 stars 41 forks source link

trouble running document *field* deletion migrations #29

Closed kiptoomm closed 3 years ago

kiptoomm commented 3 years ago

Based on the official docs, I have been trying to implement a migration that removes some deprecated fields in my documents. Here's the error I have consistently faced:

Update() requires either a single JavaScript object or an alternating list of field/value pairs that can be followed by an optional precondition. Value for argument "dataOrField" is not a valid Firestore document. Couldn't serialize object of type "DeleteTransform" (found in field "test1"). Firestore doesn't support JavaScript objects with custom prototypes (i.e. objects that were created via the "new" operator).

Here's the minimal code that reproduces the error (this same code works as expected when run as a script of its own, or when it's executed from a REST endpoint function):

// ./migrations/v0.0.1__test_field_deletion.js
const { admin } = require("firebase-admin");

const FieldValue = admin.firestore.FieldValue;

/**
 * remove deprecated fields were left behind by previous migrations
 */

module.exports.migrate = async ({ firestore }) => {
  try {
    // Get the `FieldValue` object
    const FieldValue = admin.firestore.FieldValue;

    // Grab the doc id.
    const docId = "1i9oM3IWWI2Q2VU5Pzjp";
    // Grab the collection name
    const collName = "consignments";
    // Create a document reference
    const docRef = firestore.collection(collName).doc(docId);
    let docItem = await docRef.get();

    const payload = {
      test1: FieldValue.delete()
    };

    console.log("payload ==> ", payload); // { test1: DeleteTransform {} }
    const res = await docRef.update(payload); // run the actual update op to delete the field
    console.log("deletion result: ", res);
  } catch (error) {
    console.log("error performing field delete migration: ", error.toString());
  }
};

Any ideas on how I can get it working with fireway?

My stack:

kevlened commented 3 years ago

I tested this in the latest version of fireway and it works. Two potential issues with your migration:

  1. That's an old version of fireway, which could be using an older version of firebase-admin that doesn't have FieldValue.delete(). Try installing the latest version of fireway.
  2. Migrations are provided the FieldValue class. Use that to ensure compatibility (and make your code cleaner). Here's the example that works in my test:
module.exports.migrate = async ({ firestore, FieldValue }) => {
  await firestore.collection('data').doc('doc').update({
    field1: FieldValue.delete()
  });
};

If you still have trouble after those suggestions, feel free to comment and I'll reopen the issue.

kiptoomm commented 3 years ago

...could be using an older version of firebase-admin that doesn't have FieldValue.delete(). Try installing the latest version of fireway.

Gee, I didn't realize how old the version I had before was. I upgraded it to the latest version and, without changing anything else, tested the script again and there was still no change in behavior.

Migrations are provided the FieldValue class. Use that to ensure compatibility (and make your code cleaner)

This is the change that did it! 🎉 🙇