25

Can someone help me how to rename, move or update document or collection names in Cloud Firestore?

Also is there anyway that I can access my Cloud Firestore to update my collections or documents from terminal or any application?

Community
  • 1
  • 1

4 Answers4

24

Actually there is no move method that allows you to simply move a document from a location to another. You need to create one. For moving a document from a location to another, I suggest you use the following method:

public void moveFirestoreDocument(DocumentReference fromPath, final DocumentReference toPath) {
    fromPath.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
        @Override
        public void onComplete(@NonNull Task<DocumentSnapshot> task) {
            if (task.isSuccessful()) {
                DocumentSnapshot document = task.getResult();
                if (document != null) {
                    toPath.set(document.getData())
                        .addOnSuccessListener(new OnSuccessListener<Void>() {
                            @Override
                            public void onSuccess(Void aVoid) {
                                Log.d(TAG, "DocumentSnapshot successfully written!");
                                fromPath.delete()
                                .addOnSuccessListener(new OnSuccessListener<Void>() {
                                        @Override
                                        public void onSuccess(Void aVoid) {
                                            Log.d(TAG, "DocumentSnapshot successfully deleted!");
                                        }
                                })
                                .addOnFailureListener(new OnFailureListener() {
                                        @Override
                                        public void onFailure(@NonNull Exception e) {
                                            Log.w(TAG, "Error deleting document", e);
                                        }
                                });
                            }
                        })
                        .addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                Log.w(TAG, "Error writing document", e);
                            }
                        });
                } else {
                    Log.d(TAG, "No such document");
                }
            } else {
                Log.d(TAG, "get failed with ", task.getException());
            }
        }
    });
}

In which fromPath is the location of the document that you want to be moved and toPath is the location in which you want to move the document.

The flow is as follows:

  1. Get the document from fromPath location.
  2. Write the document to toPath location.
  3. Delete the document from fromPath location.

That's it!

Rafa Viotti
  • 9,998
  • 4
  • 42
  • 62
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Thanks for your help. Can you please explain how to move collection? –  Nov 19 '17 at 11:26
  • In the same way as documents. `fromPath` instead of pointing to a document location needs to point to a collection location. – Alex Mamo Nov 19 '17 at 12:15
  • @AlexMamo Would the above work if the document has subcollection? – Snake Mar 10 '18 at 05:56
  • 4
    @Snake It will move only the documents. It won't move the subcollections if the document has subcollections. – Alex Mamo Mar 10 '18 at 11:59
  • Thank you Alex. Makes sense based on your other post – Snake Mar 10 '18 at 19:49
  • Can you do this in Python? https://stackoverflow.com/questions/60450104/how-to-copy-all-the-documents-from-one-collection-to-another-in-google-firestore – johnrao07 Mar 18 '20 at 10:45
  • @johnrao07 Try to implement it and if you find hard times in doing that, post a question here in StackOverflow so we can tale a look at it. – Alex Mamo Mar 18 '20 at 10:53
  • I would have used a transaction. In case the delete fails, you're not stuck with a duplicate. – William Choy Feb 03 '23 at 18:12
3

Here's another variation for getting a collection under a new name, it includes:

  1. Ability to retain original ID values
  2. Option to update field names

    $(document).ready(function () {

        FirestoreAdmin.copyCollection(
            'blog_posts',
            'posts'
        );

    });

=====

var FirestoreAdmin = {

    // to copy changes back into original collection
    // 1. comment out these fields
    // 2. make the same call but flip the fromName and toName 
    previousFieldName: 'color',
    newFieldName: 'theme_id',

    copyCollection: function (fromName, toName) {

        FirestoreAdmin.getFromData(
            fromName,
            function (querySnapshot, error) {

                if (ObjectUtil.isDefined(error)) {

                    var toastMsg = 'Unexpected error while loading list: ' + StringUtil.toStr(error);
                    Toaster.top(toastMsg);
                    return;
                }

                var db = firebase.firestore();

                querySnapshot.forEach(function (doc) {

                    var docId = doc.id;
                    Logr.debug('docId: ' + docId);

                    var data = doc.data();
                    if (FirestoreAdmin.newFieldName != null) {

                        data[FirestoreAdmin.newFieldName] = data[FirestoreAdmin.previousFieldName];
                        delete data[FirestoreAdmin.previousFieldName];
                    }

                    Logr.debug('data: ' + StringUtil.toStr(data));

                    FirestoreAdmin.writeToData(toName, docId, data)
                });
            }
        );
    },

    getFromData: function (fromName, onFromDataReadyFunc) {

        var db = firebase.firestore();

        var fromRef = db.collection(fromName);
        fromRef
            .get()
            .then(function (querySnapshot) {

                onFromDataReadyFunc(querySnapshot);
            })
            .catch(function (error) {

                onFromDataReadyFunc(null, error);
                console.log('Error getting documents: ', error);
            });
    },

    writeToData: function (toName, docId, data) {

        var db = firebase.firestore();
        var toRef = db.collection(toName);

        toRef
            .doc(docId)
            .set(data)
            .then(function () {
                console.log('Document set success');
            })
            .catch(function (error) {
                console.error('Error adding document: ', error);
            });

    }

}

=====

Here's the previous answer where the items are added under new IDs

        toRef
            .add(doc.data())
            .then(function (docRef) {
                console.log('Document written with ID: ', docRef.id);
            })
            .catch(function (error) {
                console.error('Error adding document: ', error);
            });   
Gene Bo
  • 11,284
  • 8
  • 90
  • 137
  • 2
    Since the OP's question has the [tag:android] tag, looks like your answer does not answer his/her question. – Edric Dec 26 '18 at 08:18
0

I solved this issue in Swift. You retrieve info from the document, put it into a new document in new location, delete old document. Code looks like this:

    let sourceColRef = self.db.collection("/Users/users/Collection/")
    colRef.document("oldDocument").addSnapshotListener { (documentSnapshot, error) in
                if let error = error {
                            print(error)
                        } else {
                            DispatchQueue.main.async {
                            if let document = documentSnapshot?.data() {
                                
                                let field1 = document["Field 1"] as? String // or Int, or whatever you have)
                                let field2 = document["Field 2"] as? String
                                let field3 = document["Field 3"] as? String
                                
                                
                  let newDocRef = db.document("/Users/users/NewCollection/newDocument")
                                newDocRef.setData([
                                        "Field 1" : field1!,
                                        "Field 1" : field2!,
                                        "Field 1" : field3!,
                                        
                                ])
                            }
                          }
                        }
                    }
            
            sourceColRef.document("oldDocument").delete()
0

// Try running a batch with deleting from source and setting on destination.

public void moveDocument(final DocumentReference source,
                         final DocumentReference dest) {
    source.get().addOnSuccessListener(doc -> {
        if (doc.getData() != null) {
            runOnBatch(b -> {
                b.set(source, doc.getData());
                b.delete(dest);
            });
        }
    });
}


public void runOnBatch(Consumer<WriteBatch> supplier) {
    final WriteBatch batch = myRef.batch();

    supplier.accept(batch);

    batch.commit()
            .addOnFailureListener(this::handleFailure)
            .addOnSuccessListener(task -> logSuccess(format("Batch optession success")));
}
Nandkishor
  • 149
  • 2
  • 12