2016-11-09 10 views
4

Firebaseにカウントクエリがないこと、カウンタを持つメソッドが2つ、クライアント側ですべてのデータを取得すること、またはデータベースにカウント値を格納することがわかっています。私はこの第2の方法を使用します。なぜなら、第1の方法はデータが少ないときだけ有効であるからです。Firebaseカウンター、大量更新ケース

このメソッドの問題は、私は多くの同時ライターを持つことができます、私はデータが格納されていない場合、インクリメントまたはデクリメントカウンタでデータを保存しようとする私の方法でこの問題を解決した。

OKこの方法は1つのカウンタのみを変更する場合にはうまくいきましたが、別のケースでは1つのトランザクションで多くの異なるカウンタを変更する必要があります。このモードでは、異なる試行後にデータを保存できないなぜなら、私たちは多くの異なるノードに同時に多くのライターを置くことができるからです。アトミックな更新とデータ構造の一例は以下の通りです:

私はこの

"comment": { 
    "counter": {}, 
    "Data": { 
     "$Comment":{} 
    } 
} 


comment/counter = val + 1 
comment/Data/comment1 = data 

を保存する場合は、私が更新に失敗した場合、他の作家はカウンタを更新しているので、それは私が新しいと再試行することができたときだけで動作しますカウンタ値と、通常は最初の時間の後、私は成功して操作を締結、私は、ユーザーおよびすべての彼の行動を削除したい場合は、たとえば、私はこのタイプのデータを格納したい

"comment":{ 
    "counter":{}, 
    "Data": { 
    "$Comment":{} 
    } 
}, 

"$user": { 
    "follower":{ 
    "counter":{}, 
    "data":{ 
     "$Follower": {} 
    } 
    } 
} 
comment/counter = val - 1 
comment/Data/comment2 = null 
user1/follower/counter = val - 1 
user1/follower/data/user30 = null 
user2/follower/counter = val - 1 
user2/follower/data/user30 = null 
user3/follower/counter = val - 1 
user3/follower/data/user30 = null 

見えるのそれ一括更新の場合、私は多くのカウンターを更新する必要があります。この場合、異なる再試行後にすべてのカウンタを更新することが不可能であることは非常に簡単です。 1 -

別の場合は、この場合、この

"photo":{ 
    "$photo":{ 
    "comment":{ 
     "counter":{}, 
     "Data": { 
     "$Comment":{} 
     } 
    } 
} 

photo/10/comment/counter = val - 1 
photo/10/comment/Data/comment1 = null 
photo/10/comment/counter = val - 1 
photo/10/comment/Data/comment2 = null 
photo/10/comment/counter = val - 1 
photo/10/comment/Data/comment3 = null 

ある私は値+1または値が等しいとすることができる同じカウンタと異なるコメントを削除しようとするので、カウンタを更新することは不可能です私はすべてのユーザーデータを削除したい場合、彼は同じ写真にいくつかのコメントを書く可能性がありますが、カウンタは単一のトランザクションでのみ更新できるので、このコメントのすべてを1つのトランザクションで削除することはできません。

どのようなタイプのデータベース(sqlまたはnosql)にも存在するカウントクエリが存在しないため、多くの複雑な問題が発生します。私はなぜなのか理解していない。これには時間を無駄にすることなく解決できる多くの問題が含まれます

以下は、カウンタを更新するための私のjavascript機能です。それあなたがtransactionsを探しているので、他の人の同時ライター

this.singleUpdate = function (paths, increment, countPath, retryCounter, callback) { 
      firebase.database().ref(countPath).once('value', function (counter) { 
       var value = counter.val() ? counter.val().value : 0; 
       var countValue = increment ? value + 1 : value - 1; 
       paths[countPath] = { value: null };     

       if (!increment && countValue == 0) { paths[countPath] = null; } 
       else { 
        paths[countPath].value = countValue;      
       } 

       firebase.database().ref().update(paths, function (error) { 
        if (error) { 
         retryCounter++; 
         if (retryCounter < 3) { singleUpdate(paths, increment, countPath, retryCounter, callback); } 
         else { callback(false, error); } 
        } else { 
         return callback(true, countValue); 
        } 
       }); 
      }); 
     } 
+0

これは質問ですか?もしそうなら、私たちのデータを理解するためにFirebase構造の問題とスニペットを示すコード例をテキストとして提供してください。 – Jay

+0

私はカウンタを更新するために私の機能をポストしていますが、問題はクライアントコードではなくfirebaseのデータ構造内にあります。しかしfirebaseにカウントのクエリが存在しないこれは私が考えているユニークな方法です – DThink

答えて

0

の更新に失敗した場合に自分を思い出す再帰関数である、あなたはありませんか?

な増分カウンタなどの同時 の変更によって破損している可能性があり、データ、で作業する場合、あなたが取引 操作を使用することができます。この操作には、更新機能とオプションの補完コールバック を与えることができます。更新関数は、現在の の状態を引数としてとり、 が書きたい新しい状態を返します。別のクライアントが の新しい値の書き込みに成功する前にその場所に書き込みを行った場合、更新機能は新しい現在の値で再び と呼ばれ、書き込みが再試行されます。

ドキュメントからの例:追加など

function toggleStar(postRef, uid) { 
    postRef.transaction(function(post) { 
    if (post) { 
     if (post.stars && post.stars[uid]) { 
     post.starCount--; 
     post.stars[uid] = null; 
     } else { 
     post.starCount++; 
     if (!post.stars) { 
      post.stars = {}; 
     } 
     post.stars[uid] = true; 
     } 
    } 
    return post; 
    }); 
} 

カウンタが同じ値に残りますので、あなたは、削除されたユーザーによって投稿のみコンテンツを削除することができますし、代わりにコメント/ポストのポストだった「が存在します削除済み "

+0

はい私はトランザクションを知っています。別のことは、私は1つのクエリだけでこのケースでは、私はトランザクションを使用することはできませんより多くのカウンタを更新したいですが、更新メソッドです。問題は、すべてのクライアント側のメソッドだということです。サーバー側で機能するインクリメントとデクリメントのメソッドが必要です。それ以外の場合は、多くのユーザーが異なる時間に書き込みを失敗するのは簡単です。 – DThink

+0

@DThink別のアプリサーバーはありますか?私はあなたが望むものを実装するためにGoやPythonの例を提供することができます。しかしFirebaseは一括更新のトランザクション –

+0

しか持っていません。私はnodejsスクリプトを使用しますが、メソッドは同じ、トランザクションまたは更新です。しかし、彼は私のニーズに応えません: – DThink

関連する問題