फायरबेस में, क्या सभी नोड डेटा लोड किए बिना नोड के बच्चों की संख्या प्राप्त करने का एक तरीका है?


132

आप बच्चे को गिन सकते हैं

firebase_node.once('value', function(snapshot) { alert('Count: ' + snapshot.numChildren()); });

लेकिन मेरा मानना ​​है कि यह सर्वर से उस नोड के पूरे उप-पेड़ को प्राप्त करता है। विशाल सूचियों के लिए, जो रैम और विलंबता गहन लगता है। क्या पूरी चीज़ प्राप्त किए बिना गिनती (और / या बच्चे के नामों की सूची) प्राप्त करने का एक तरीका है?


बहुत बहुत धन्यवाद, मैं इसे करने की कोशिश करता हूं और इसने मेरे लिए काम किया
अहमद महमूद

आपका कोड बड़े डेटा सेट को संभाल नहीं सकता है। मुझे जावा हीप स्पेस के कारण त्रुटि हुई। मैं अभी भी कुछ फीचर का इंतजार कर रहा हूं।
पैनापॉन्ग कोंगर्न

जवाबों:


98

आपके द्वारा दिया गया कोड स्निपेट वास्तव में डेटा के पूरे सेट को लोड करता है और फिर इसे क्लाइंट-साइड गिना जाता है, जो बड़ी मात्रा में डेटा के लिए धीमा हो सकता है।

फायरबेस के पास वर्तमान में डेटा लोड किए बिना बच्चों को गिनने का एक तरीका नहीं है, लेकिन हम इसे जोड़ने की योजना बनाते हैं।

अभी के लिए, एक समाधान बच्चों की संख्या को बनाए रखने और हर बार जब आप एक नया बच्चा जोड़ते हैं, तो उसे अपडेट करना होगा। आप आइटमों को गिनने के लिए लेनदेन का उपयोग कर सकते हैं, जैसे इस कोड में अपवार्ड ट्रैकिंग:

var upvotesRef = new Firebase('https://docs-examples.firebaseio.com/android/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes');
upvotesRef.transaction(function (current_value) {
  return (current_value || 0) + 1;
});

अधिक जानकारी के लिए, https://www.firebase.com/docs/transactions.html देखें

अद्यतन: फायरबेस ने हाल ही में जारी क्लाउड फ़ंक्शंस। क्लाउड फ़ंक्शंस के साथ, आपको अपना सर्वर बनाने की आवश्यकता नहीं है। आप बस जावास्क्रिप्ट फ़ंक्शन लिख सकते हैं और इसे फायरबेस पर अपलोड कर सकते हैं। जब भी कोई घटना होती है, तो फायरबेस कार्य को ट्रिगर करने के लिए जिम्मेदार होगा।

यदि आप उदाहरण के लिए उल्टी गिनती करना चाहते हैं, तो आपको इस तरह की एक संरचना बनानी चाहिए:

{
  "posts" : {
    "-JRHTHaIs-jNPLXOQivY" : {
      "upvotes_count":5,
      "upvotes" : {
      "userX" : true,
      "userY" : true,
      "userZ" : true,
      ...
    }
    }
  }
}

और फिर नोड के upvotes_countलिए एक नया लेखन होने पर बढ़ाने के लिए एक जावास्क्रिप्ट फ़ंक्शन लिखें upvotes

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

exports.countlikes = functions.database.ref('/posts/$postid/upvotes').onWrite(event => {
  return event.data.ref.parent.child('upvotes_count').set(event.data.numChildren());
});

क्लाउड फ़ंक्शंस से कैसे शुरुआत करें, यह जानने के लिए आप डॉक्यूमेंटेशन को पढ़ सकते हैं ।

इसके अलावा, पदों की गिनती का एक और उदाहरण यहाँ है: https://github.com/firebase/functions-samples/blob/master/child-count/functions/index.js

अपडेट जनवरी 2018

हमारे पास अब के बजाय फायरबस डॉक्स बदल गए eventहैं changeऔर context

दिए गए उदाहरण में शिकायत की त्रुटि है event.dataजो अपरिभाषित है। यह पैटर्न बेहतर काम करता है:

exports.countPrescriptions = functions.database.ref(`/prescriptions`).onWrite((change, context) => {
    const data = change.after.val();
    const count = Object.keys(data).length;
    return change.after.ref.child('_count').set(count);
});

`` `


74
क्या आपने कभी इसके लिए समर्थन जोड़ा?
जिम कूपर

20
हालांकि लेन-देन में क्लाइंट-साइड काउंटर सुरक्षित है? ऐसा लगता है कि इसे कृत्रिम रूप से वृद्धि की गिनती के लिए आसानी से हैक किया जा सकता है। यह वोटिंग सिस्टम के लिए बुरा हो सकता है।
सोविओट

16
++ ट्रांसफर लागत के बिना गिनती प्राप्त करना वास्तव में अच्छा होगा
जारेड फोर्सिथ

27
क्या यह कभी जोड़ा गया है?
एलीएजर

25
इस फीचर रोडमैप पर कोई खबर? धन्यवाद
Pandaiolo

37

इस खेल में थोड़ी देर है क्योंकि कई अन्य पहले से ही अच्छी तरह से उत्तर दे चुके हैं, लेकिन मैं साझा करूँगा कि मैं इसे कैसे लागू कर सकता हूं।

यह इस तथ्य पर टिका है कि फायरबेस रेस्ट एपीआई एक shallow=trueपैरामीटर प्रदान करता है ।

मान लें कि आपके पास एक postऑब्जेक्ट है और हर एक के पास कई नंबर हो सकते हैं comments:

{
 "posts": {
  "$postKey": {
   "comments": {
     ...  
   }
  }
 }
}

आप स्पष्ट रूप से सभी टिप्पणियों को प्राप्त नहीं करना चाहते हैं, बस टिप्पणियों की संख्या।

मान लें कि आपके पास किसी पोस्ट की कुंजी है, तो आप एक GETअनुरोध भेज सकते हैं https://yourapp.firebaseio.com/posts/[the post key]/comments?shallow=true

यह कुंजी-मूल्य जोड़े की एक वस्तु लौटाएगा, जहां प्रत्येक कुंजी एक टिप्पणी की कुंजी है और इसका मूल्य है true:

{
 "comment1key": true,
 "comment2key": true,
 ...,
 "comment9999key": true
}

इस प्रतिक्रिया का आकार समतुल्य डेटा का अनुरोध करने की तुलना में बहुत छोटा है, और अब आप अपने मूल्य को खोजने के लिए प्रतिक्रिया में कुंजियों की संख्या की गणना कर सकते हैं (उदाहरण टिप्पणी = Object.keys(result).length)।

यह आपकी समस्या को पूरी तरह से हल नहीं कर सकता है, क्योंकि आप अभी भी लौटे कुंजी की संख्या की गणना कर रहे हैं, और आप आवश्यक रूप से मूल्य में परिवर्तन नहीं कर सकते हैं, लेकिन यह आपके डेटा में किसी भी बदलाव की आवश्यकता के बिना लौटे डेटा के आकार को बहुत कम कर देता है। स्कीमा।


पिछले उत्तर के बाद से उथला = सही होने के बाद से यह एक स्वीकृत उत्तर हो सकता है। खुद को देखने का समय नहीं था, इसलिए कुछ दिनों तक इंतजार करना होगा कि लोग क्या सोचते हैं ...
josh

1
उथला शायद अब के लिए सबसे अच्छा विकल्प है, लेकिन यह संपीड़न के साथ वापस नहीं आया है और बड़े डेटा सेट के लिए बहुत धीमा और अनुभव बन सकता है
म्बेवडा

यदि टिप्पणी कुंजियों में कोई बूलियन मान नहीं है, लेकिन इसके बजाय बच्चों के पास है, तो क्या यह अभी भी कुंजियों के कुंजी-मूल्य जोड़े को वापस करता है?
अल्तेज


3
केवल यह इंगित करने के लिए कि आपको .jsonURL के अंत में संलग्न करना है, उदाहरण के लिए:https://yourapp.firebaseio.com/posts/comments.json?shallow=true
Osama Xäwãñz

22

गणना करें जैसे ही आप जाते हैं - और इसे लागू करने के लिए सत्यापन का उपयोग करें। मैंने इसे एक साथ हैक किया - अद्वितीय वोटों और गिनती की गिनती रखने के लिए जो ऊपर आती रहती है!। लेकिन इस बार मैंने अपने सुझाव का परीक्षण किया है! (कट / पेस्ट त्रुटियों के बावजूद!)।

यहां 'ट्रिक' को नोड प्राथमिकता के रूप में वोट गणना के रूप में उपयोग करना है ...

डेटा है:

वोट / $ जारी।

,"vote": {
  ".read" : true
  ,".write" : true
  ,"$issue" : {
    "user" : {
      "$user" : {
        ".validate" : "!data.exists() && 
             newData.val()==data.parent().parent().child('count').getPriority()+1 &&
             newData.val()==newData.GetPriority()" 

उपयोगकर्ता केवल एक बार मतदान कर सकता है और & quot; वर्तमान गणना की तुलना में एक अधिक होना चाहिए && डेटा मान प्राथमिकता के समान होना चाहिए।

      }
    }
    ,"count" : {
      ".validate" : "data.parent().child(newData.val()).val()==newData.getPriority() &&
             newData.getPriority()==data.getPriority()+1 "
    }

गिनती (अंतिम मतदाता वास्तव में) - वोट मौजूद होना चाहिए और इसकी गिनती बराबर न्यूकाउंट, && newcount (प्राथमिकता) केवल एक के ऊपर जा सकती है।

  }
}

अलग-अलग उपयोगकर्ताओं द्वारा 10 वोट जोड़ने के लिए टेस्ट स्क्रिप्ट (उदाहरण के लिए, आईडी के फेक, उपयोगकर्ता को चाहिए। उत्पादन में)। सत्यापन विफल होने के लिए (i--) 10 तक की गणना करें।

<script src='https://cdn.firebase.com/v0/firebase.js'></script>
<script>
  window.fb = new Firebase('https:...vote/iss1/');
  window.fb.child('count').once('value', function (dss) {
    votes = dss.getPriority();
    for (var i=1;i<10;i++) vote(dss,i+votes);
  } );

function vote(dss,count)
{
  var user='user/zz' + count; // replace with auth.id or whatever
  window.fb.child(user).setWithPriority(count,count);
  window.fb.child('count').setWithPriority(user,count);
}
</script>

यहां 'जोखिम' यह है कि एक वोट डाला जाता है, लेकिन गिनती अपडेट नहीं की जाती है (हॉकिंग या स्क्रिप्ट विफलता)। यही कारण है कि वोटों की एक अद्वितीय 'प्राथमिकता' होती है - स्क्रिप्ट को वास्तव में यह सुनिश्चित करके शुरू करना चाहिए कि वर्तमान गणना की तुलना में प्राथमिकता के साथ कोई वोट नहीं है, अगर यह है कि इसे स्वयं करने से पहले उस लेनदेन को पूरा करना चाहिए - अपने ग्राहकों को साफ करने के लिए प्राप्त करें तुम्हारे लिए :)

गणना शुरू करने से पहले प्राथमिकता के साथ आरंभ करने की आवश्यकता है - फोर्ज आपको ऐसा करने की अनुमति नहीं देता है, इसलिए स्टब स्क्रिप्ट की आवश्यकता है (सत्यापन सक्रिय होने से पहले!)।


यह कमाल का है!!! हालांकि संघर्षों पर क्या होता है? यानी, दो लोग एक ही समय पर मतदान करते हैं? आदर्श रूप से आप अपने आप में से एक वोट को छोड़ने के बजाय स्वचालित रूप से हल करना चाहते हैं ... हो सकता है कि वोट एक लेनदेन में हो?
जोश

हाय जोश, तार्किक रूप से एक वास्तविक वोट केवल तभी विफल हो सकता है जब एक पिछला वोट डाला गया हो, लेकिन कुल अपडेट नहीं किया गया (अभी तक)। मेरा दूसरा अंतिम पैरा शामिल है - मैं पिछले मतदाताओं के लिए कुल अपडेट वैसे भी (हर बार) करूंगा - अगर इसकी जरूरत नहीं थी, तो क्या? और फिर यह वोट अपडेट होता है। जब तक वोट ठीक काम करता है। यदि आपका 'कुल' अपडेट विफल रहता है, तो अगला मतदाता इसे ठीक करेगा, फिर से - तो क्या?
23

मुझे वास्तव में सिर्फ यह कहने का मोह है कि 'काउंट' नोड का 'पिछला पिछला वोट' नोड होना चाहिए - इसलिए प्रत्येक मतदाता / ग्राहक अपडेट / उस नोड / मूल्य को सुधारता / सुधारता है और फिर अपना स्वयं का वोट जोड़ता है - (अगले मतदाता को अपडेट देने देता है) कुल मिलाकर 'यह' वोट)। - अगर आपको मेरा बहाव मिलता है ...
पेपरिन

4

नोड गणना के लिए एक क्लाउड फ़ंक्शन लिखें और अपडेट करें।

// below function to get the given node count.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

exports.userscount = functions.database.ref('/users/')
    .onWrite(event => {

      console.log('users number : ', event.data.numChildren());


      return event.data.ref.parent.child('count/users').set(event.data.numChildren());
    }); 

देखें: https://firebase.google.com/docs/functions/database-events

root-- | | -सुअर (इस नोड में सभी उपयोगकर्ता सूची शामिल हैं) |
| -count | -userscount: (यह नोड उपयोगकर्ता गणना के साथ क्लाउड फ़ंक्शन द्वारा गतिशील रूप से जोड़ा गया है)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.