2017-10-03 3 views

Répondre

2

Solution simple

Si vous connaissez le nombre de résultats du jeu en cours d'écriture sera au plus une fois par seconde, vous pouvez utiliser les fonctions Cloud pour mettre à jour un document distinct average/score. Pour chaque ajout de résultat de jeu, si le document n'existait pas, définissez un champ appelé count sur 1 et un champ appelé score sur le score du jeu. Si le document existe, ajoutez 1 au champ appelé count et ajoutez le score au champ appelé score.

Maintenant, pour interroger le score moyen, il suffit de lire average/score et de diviser score par count.

Solution évolutive

Si vous pensez ou savez le nombre de résultats du jeu en cours d'écriture dépassera une fois par seconde, vous aurez besoin d'appliquer un style de compteur distribué de la solution simple.

Votre modèle de données pour le document moyen utilisera les sous-collections et ressembler à:

// average/score 
{ 
    "num_shards": NUM_SHARDS, 
    "shards": [subcollection] 
} 

// average/score/shards/${NUM} 
{ 
    "count": 115, 
    "score": 1472 
} 

Pour rendre votre code de mise à jour plus simple, vous pouvez initialiser d'abord ces tessons avec:

// ref points to db.collection('average').doc('score') 
function createAverageAggregate(ref, num_shards) { 
    var batch = db.batch(); 

    // Initialize the counter document 
    batch.set(ref, { num_shards: num_shards }); 

    // Initialize each shard with count=0 
    for (let i = 0; i < num_shards; i++) { 
     let shardRef = ref.collection('shards').doc(i.toString()); 
     batch.set(shardRef, { count: 0, count: 0 }); 
    } 

    // Commit the write batch 
    return batch.commit(); 
} 

Mise à jour du l'agrégat moyen dans les fonctions Cloud est maintenant aussi simple que:

// ref points to db.collection('average').doc('score') 
function updateAverage(db, ref, num_shards) { 
    // Select a shard of the counter at random 
    const shard_id = Math.floor(Math.random() * num_shards).toString(); 
    const shard_ref = ref.collection('shards').doc(shard_id); 

    // Update count in a transaction 
    return db.runTransaction(t => { 
     return t.get(shard_ref).then(doc => { 
      const new_count = doc.data().count + 1; 
      const new_score = doc.data().score + 1; 
      t.update(shard_ref, { count: new_count, score: new_score }); 
     }); 
    }); 
} 

G ise la moyenne peut alors se faire avec:

// ref points to db.collection('average').doc('score') 
function getAverage(ref) { 
    // Sum the count and sum the score of each shard in the subcollection 
    return ref.collection('shards').get().then(snapshot => { 
     let total_count = 0; 
     let total_score = 0; 
     snapshot.forEach(doc => { 
      total_count += doc.data().count; 
      total_score += doc.data().score; 
     }); 
     return total_score/total_count; 
    }); 
} 

Le taux d'écriture, vous pouvez obtenir dans ce système est NUM_SHARDS par seconde, afin de planifier en conséquence. Remarque: Vous pouvez commencer petit et augmenter le nombre de fragments facilement. Il suffit de créer une nouvelle version de createAverageAggregate pour augmenter le nombre de partitions en initialisant les nouvelles, puis en mettant à jour le paramètre num_shards. Cela devrait être automatiquement pris en charge par vos fonctions updateAverage et getAverage.