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?
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
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.
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>()