Add new field or change the structure on all Firestore documents

前端 未结 5 708
感动是毒
感动是毒 2021-02-02 13:11

Consider a collection of users. Each document in the collection has name and email as fields.

{
  \"users\": {
    \"uid1\         


        
5条回答
  •  栀梦
    栀梦 (楼主)
    2021-02-02 13:39

    I wrote some routines to help automate this process back when I posted the question. I did not post them since these are a bit rudimentary and I was hoping for an elegant Firestore-based solution. Because such solution is not still available, here are the functions I wrote.

    In short, we have functions for renaming a field, adding a field, or deleting a field. To rename a field, different functions are used depending on the data type. Maybe someone could generalise this better? The functions below are:

    • add_field: Adds a field in all documents of a collection.
    • delete_field: Deletes a field in all documents of a collection.
    • rename_*_field: Renames a field containing a certain data type (*) in all documents of a collection. Here I include examples for String, Integer, and Date.

    Add field:

    public void add_field (final String key, final Object value, final String collection_ref) {
        FirebaseFirestore.getInstance().collection(collection_ref).get()
                .addOnCompleteListener(new OnCompleteListener() {
                    @Override
                    public void onComplete(@NonNull Task task) {
                        if (task.isSuccessful()) {
                            WriteBatch batch = db.batch();
    
                            for (DocumentSnapshot document : task.getResult()) {
                                DocumentReference docRef = document.getReference();
                                Map new_map = new HashMap<>();
                                new_map.put(key, value);
                                batch.update(docRef, new_map);
                            }
                            batch.commit();
                        } else {
                            // ... "Error adding field -> " + task.getException()
                        }
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        // ... "Failure getting documents -> " + e
                    }
                });
    }
    

    Delete field:

    public void delete_field (final String key, final String collection_ref) {
        FirebaseFirestore.getInstance().collection(collection_ref).get()
                .addOnCompleteListener(new OnCompleteListener() {
                    @Override
                    public void onComplete(@NonNull Task task) {
                        if (task.isSuccessful()) {
    
                            WriteBatch batch = db.batch();
    
                            for (DocumentSnapshot document : task.getResult()) {
                                DocumentReference docRef = document.getReference();
                                Map delete_field = new HashMap<>();
                                delete_field.put(key, FieldValue.delete());
                                batch.update(docRef, delete_field);
                            }
                            // Commit the batch
                            batch.commit().addOnCompleteListener(new OnCompleteListener() {
                                @Override
                                public void onComplete(@NonNull Task task) {
                                    // ...
                                }
                            });
    
                        } else {
                            // ... "Error updating field -> " + task.getException()
                        }
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        // ... "Failure getting notices -> " + e
                    }
                });
    }
    

    Rename field:

    public void rename_string_field (final String old_key, final String new_key, final String collection_ref) {
        FirebaseFirestore.getInstance().collection(collection_ref).get()
                .addOnCompleteListener(new OnCompleteListener() {
                    @Override
                    public void onComplete(@NonNull Task task) {
                        if (task.isSuccessful()) {
    
                            WriteBatch batch = db.batch();
    
                            for (DocumentSnapshot document : task.getResult()) {
                                DocumentReference docRef = document.getReference();
                                String old_value = document.getString(old_key);
    
                                if (old_value != null) {
                                    Map new_map = new HashMap<>();
                                    new_map.put(new_key, old_value);
    
                                    Map delete_old = new HashMap<>();
                                    delete_old.put(old_key, FieldValue.delete());
    
                                    batch.update(docRef, new_map);
                                    batch.update(docRef, delete_old);
                                }
                            }
                            // Commit the batch
                            batch.commit().addOnCompleteListener(new OnCompleteListener() {
                                @Override
                                public void onComplete(@NonNull Task task) {
                                    // ...
                                }
                            });
    
                        } else {
                            // ... "Error updating field -> " + task.getException()
                        }
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        // ... "Failure getting notices ->" + e
                    }
                });
    }
    
    public void rename_integer_field (final String old_key, final String new_key, final String collection_ref) {
        FirebaseFirestore.getInstance().collection(collection_ref).get()
                .addOnCompleteListener(new OnCompleteListener() {
                    @Override
                    public void onComplete(@NonNull Task task) {
                        if (task.isSuccessful()) {
    
                            WriteBatch batch = db.batch();
    
                            for (DocumentSnapshot document : task.getResult()) {
                                DocumentReference docRef = document.getReference();
                                int old_value = document.getDouble(old_key).intValue();
                                Integer ov = old_value;
                                if (ov != null) {
                                    Map new_map = new HashMap<>();
                                    new_map.put(new_key, old_value);
    
                                    Map delete_old = new HashMap<>();
                                    delete_old.put(old_key, FieldValue.delete());
    
                                    batch.update(docRef, new_map);
                                    batch.update(docRef, delete_old);
                                }
                            }
                            // Commit the batch
                            batch.commit().addOnCompleteListener(new OnCompleteListener() {
                                @Override
                                public void onComplete(@NonNull Task task) {
                                    // ...
                                }
                            });
    
                        } else {
                            // ... "Error updating field -> " + task.getException()
                        }
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        // ... "Failure getting notices -> " + e
                    }
                });
    }
    
    public void rename_date_field (final String old_key, final String new_key, final String collection_ref) {
        FirebaseFirestore.getInstance().collection(collection_ref).get()
                .addOnCompleteListener(new OnCompleteListener() {
                    @Override
                    public void onComplete(@NonNull Task task) {
                        if (task.isSuccessful()) {
    
                            WriteBatch batch = db.batch();
    
                            for (DocumentSnapshot document : task.getResult()) {
                                DocumentReference docRef = document.getReference();
                                Date old_value = document.getDate(old_key);
                                if (old_value != null) {
                                    Map new_map = new HashMap<>();
                                    new_map.put(new_key, old_value);
    
                                    Map delete_old = new HashMap<>();
                                    delete_old.put(old_key, FieldValue.delete());
    
                                    batch.update(docRef, new_map);
                                    batch.update(docRef, delete_old);
                                }
                            }
                            // Commit the batch
                            batch.commit().addOnCompleteListener(new OnCompleteListener() {
                                @Override
                                public void onComplete(@NonNull Task task) {
                                    // ...
                                }
                            });
    
                        } else {
                            // ... "Error updating field -> " + task.getException()
                        }
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        // ... "Failure getting notices -> " + e
                    }
                });
    }
    

提交回复
热议问题