5 votes

Cloud Functions for Firestore : accès aux données des collections parentales

De nombreux blogs suggèrent de passer à Cloud Firestore parce que c'est facile et bien sécurisé. Je viens de Realtime Database et à l'époque où j'utilisais Functions + RD, il était facile de naviguer dans les déclencheurs de documents, tels que ref.parent

Ma configuration est la suivante :

  • Utilisateurs
    • {nom d'utilisateur}
      • Dernière vue : "données"
      • {formulaires}
        • {formid}

Cependant, j'ai ajouté un déclencheur de document avec onCreate et je veux obtenir la valeur de last_seen :

exports.updateUser = functions.firestore.document('users/{userId}/forms/{formid}').onCreate((snap, context) => {

    const newValue = snap.data();
    console.log("test value : " + newValue.test); // works
    console.log("form id: " + context.params.formid); // works
    console.log("user last seen : " + newValue.last_seen); // doesn't work, can't access the parent collection data

});

21voto

Dennis Smolek Points 4288

Je comprends tout à fait la confusion avec le passage à Firestore mais c'est presque exactement la même chose dans ce cas.

En temps réel, vous avez l'instantané :

exports.doStuff = functions.database.ref('/users/{userId}/forms/{formId}')
    .onCreate((snapshot, context) => {
    const ref = snapshot.ref;
    const userRef = ref.parent.parent;
    userRef.once('value').then(parentSnap => {
        const user = parentSnap.val();
        const lastSeen = user.last_seen;
    });
});

Dans Firestore :

exports.doStuff = functions.firestore.document.onCreate('/users/{userId}/forms/{formId}')
    .onCreate((snapshot, context) => {
    const ref = snapshot.ref;
    const userRef = ref.parent.parent;
    userRef.get().then(parentSnap => {
        const user = parentSnap.data();
        const lastSeen = user.last_seen;
    });
});

Une autre chose à considérer est que vous passez le userId dans vos paramètres afin que vous puissiez simplement construire votre propre DocumentReference (en supposant que vous utilisez également firebaseAdmin).

functions.firestore.document.onCreate('/users/{userId}/forms/{formId}')
    .onCreate((snapshot, context) => {
    const userId = context.params.userId;
    const userRef = firebaseAdmin.firestore().collection('users').doc(userId);
    userRef.get().then(parentSnap => {
        const user = parentSnap.data();
        const lastSeen = user.last_seen;
    });
});

Il vous permet également de découpler votre logique pour les fonctions que vous utilisez souvent, considérez-le comme une méthode "d'aide" : (NOTE, j'ai changé pour async/await par accident, c'est un peu plus propre)

functions.firestore.document.onCreate('/users/{userId}/forms/{formId}')
    .onCreate(async (snapshot, context) => {
    const userId = context.params.userId;
    const lastSeen = await getLastSeen(userId);
});

// == Helper Functions ==-------------------
export async getLastSeen(userId) {
    if (!userId) return Promise.reject('no userId');
    // User Ref
    const userSnap = await firebaseAdmin.firestore().collection('users').doc(userId).get();
    return userSnap.data().last_seen;
}

Vous pouvez maintenant utiliser getLastSeen() chaque fois que vous en avez besoin, et si vous apportez un changement, vous ne devez régler que cette seule fonction. Si ce n'est pas quelque chose que vous appelez souvent, alors ne vous inquiétez pas, mais j'envisagerais peut-être une getUser() aide...

1voto

Doug Stevenson Points 6978

Dans votre code, snap est un DocumentSnapshot objet de type. Comme vous pouvez le voir dans la documentation API liée, il existe un objet de type ref sur cet objet qui vous donne un DocumentReference pointant vers le document qui a été ajouté. Cet objet a parent qui vous donne un RéférenceCollection qui pointe vers la collection dans laquelle le document existe, et qui possède également une balise parent propriété. Utilisez donc ces propriétés pour naviguer dans votre base de données selon vos besoins.

0voto

Obtenez la référence où le changement a eu lieu, remontez de deux niveaux et saisissez les données en utilisant la méthode suivante ref.once() fonction :

exports.updateUser = functions.firestore.document('users/{userId}/forms/{formid}').onCreate( async (snap, context) => {

    // Get the reference where the change took place
    const changeRef = snap.after.ref;

    // Move to grandad level (2 levels up)
    const userIdRef = changeRef.parent.parent;

    // Capture data
    const snapshot = await userIdRef.once('value');

    // Get variable
    const lastSeen = snapshot.val().last_seen;

    // Do your stuff...

    return null;

});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X