web-dev-qa-db-fra.com

Comment obtenir l'ID de document pour un document Firestore à l'aide de classes de données Kotlin

J'ai la classe de données Kotlin 

data class Client(

    val name: String = "",
    val email: String = "",
    val phone: String ="") {
constructor():this("","","")}

Firestore a très bien renseigné les données dans la classe, mais je ne sais pas trop comment obtenir l'ID du document dans la classe de données sans avoir à le définir dans le document lui-même. Est-ce possible? 

7
ZerroShadows

Oui, il est possible d’obtenir un identifiant sans le stocker, en utilisant DocumentSnapshot. Je vais essayer de construire des exemples complets ici.

J'ai créé une classe Model générale pour contenir l'identifiant: 

@IgnoreExtraProperties
public class Model {
    @Exclude
    public String id;

    public <T extends Model> T withId(@NonNull final String id) {
        this.id = id;
        return (T) this;
    }
}

Ensuite, vous l’étendez avec n’importe quel modèle, vous n'avez rien à implémenter: 

public class Client extends Model

Si j'ai la liste des clients ici, j'essaie d'interroger la liste pour obtenir uniquement des clients avec age == 20

clients.whereEqualTo("age", 20)
        .get()
        .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
            @Override
            public void onComplete(@NonNull Task<QuerySnapshot> task) {
                if (task.isSuccessful()) {
                    for (DocumentSnapshot documentSnapshot : task.getResult().getDocuments()) {
                        // here you can get the id. 
                        Client client = document.toObject(client.class).withId(document.getId());
                       // you can apply your actions...
                    }
                } else {

                }
            }
        });

Et si vous utilisez EventListener, vous pouvez également obtenir l'ID comme suit: 

clients.addSnapshotListener(new EventListener<QuerySnapshot>() {
    @Override
    public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
        for (DocumentChange change : documentSnapshots.getDocumentChanges()) {
            // here you can get the id. 
                        Client client = document.toObject(client.class).withId(document.getId());
                       // you can apply your actions...
        }
    }
});

documentSnapshot.getId()) vous obtiendra l'identifiant du document de la collection sans enregistrer l'identifiant dans le document.

Utiliser Model ne vous laissera éditer aucun de vos modèles, et n'oubliez pas d'utiliser @IgnoreExtraProperties

17
amrro

Voici comment j'ai résolu le problème. 

data class Client(
    val name: String = "",
    val email: String = "",
    val phone: String ="",
    @get:Exclude var id: String = "") {
constructor():this("","","")
}

J'utilise @get: Exclude sur l'identifiant pour m'assurer que l'identifiant n'est pas envoyé à Firestore lors de l'enregistrement, puis lors de l'extraction de la liste des clients

snapshot.documents.mapTo(list) {
            var obj = it.toObject(Client::class.Java)
            obj.id = it.id
            obj
        }

Définition de l'identifiant du nouvel objet sur l'identifiant de la référence du document.

4
ZerroShadows

Je viens d'améliorer la solution de @iCediCe et d'ajouter des méthodes à DocumentSnapshot et QuerySnapshot.

interface HasId {
    var id : String
}

inline fun <reified T : HasId> DocumentSnapshot.toObjectWithId(): T {
    return this.toObject(T::class.Java)!!.also {
        it.id = this.id
    }
}

inline fun <reified T : HasId> QuerySnapshot.toObjectsWithId(): List<T> {
    return this.documents.map {
        it.toObjectWithId<T>()
    }
}

Et utilisation:

data class User(
    @get:Exclude
    override var id: String,
    ...
): HasId


val user = documentSnapshot.toObjectWithId<User>()
val users = querySnapshot.toObjectsWithId<User>()
2
comm1x