নতুন ফায়ারবেস ডাটাবেস, ক্লাউড ফায়ার স্টোর ব্যবহার করে কোনও সংগ্রহ কতটি আইটেম ব্যবহার করেছে তা গণনা করা সম্ভব?
যদি তা হয় তবে আমি কীভাবে করব?
নতুন ফায়ারবেস ডাটাবেস, ক্লাউড ফায়ার স্টোর ব্যবহার করে কোনও সংগ্রহ কতটি আইটেম ব্যবহার করেছে তা গণনা করা সম্ভব?
যদি তা হয় তবে আমি কীভাবে করব?
উত্তর:
অনেক প্রশ্নের মতোই উত্তরটি - এটি নির্ভর করে ।
সামনের প্রান্তে প্রচুর পরিমাণে ডেটা হ্যান্ডেল করার সময় আপনার খুব সতর্ক হওয়া উচিত। আপনার সামনের প্রান্তটি স্বাচ্ছন্দ্য বোধ করার শীর্ষে, ফায়ারস্টোর আপনার তৈরি করা পড়ার জন্য আপনাকে প্রতি মিলিয়ন। 0.60 লাগিয়ে দেয় ।
যত্ন সহ ব্যবহার করুন - সম্মুখভাগ ব্যবহারকারীর অভিজ্ঞতা হিট নিতে পারে
সামনের প্রান্তে এটিকে হ্যান্ডেল করা যতক্ষণ না আপনি ফিরে আসা অ্যারের সাথে খুব বেশি যুক্তি না দেখিয়ে ঠিক হওয়া উচিত।
db.collection('...').get().then(snap => {
size = snap.size // will return the collection size
});
যত্ন সহ ব্যবহার করুন - ফায়ার স্টোর পড়ার অনুরোধগুলির জন্য অনেক বেশি খরচ হতে পারে
সামনের প্রান্তে এটি হ্যান্ডেল করা সম্ভব নয় কারণ এটি ব্যবহারকারী সিস্টেমকে ধীর করে দেওয়ার খুব বেশি সম্ভাবনা রয়েছে। আমাদের এই লজিক সার্ভারটি পরিচালনা করতে হবে এবং কেবল আকারটি ফিরিয়ে আনতে হবে।
এই পদ্ধতির অপূর্ণতা হ'ল আপনি এখনও ফায়ার স্টোর পঠনগুলি (আপনার সংগ্রহের আকারের সমান) অনুরোধ করছেন যা দীর্ঘকালীন সময়ে আপনার প্রত্যাশার চেয়ে বেশি ব্যয় করতে পারে।
মেঘ ফাংশন:
...
db.collection('...').get().then(snap => {
res.status(200).send({length: snap.size});
});
সামনের অংশ:
yourHttpClient.post(yourCloudFunctionUrl).toPromise().then(snap => {
size = snap.length // will return the collection size
})
সর্বাধিক স্কেলেবল সমাধান
FieldValue.increment ()
এপ্রিল 2019 হিসাবে ফায়ার স্টোর এখন সম্পূর্ণ পরমাণুভাবে এবং ডেটা পূর্বে পড়া না করে বাড়ানো কাউন্টারের অনুমতি দেয় । একসাথে একাধিক উত্স থেকে আপডেট করার সময় (পূর্বে লেনদেনের সাহায্যে সমাধান করা হয়েছে) এমনকি আমাদের কার্যকর ডাটাবেসের পাঠ্য সংখ্যা হ্রাস করার পরেও আমাদের সঠিক পাল্টা মানগুলি নিশ্চিত করে।
মুছে ফেলা বা তৈরি করা কোনও নথির কথা শুনে আমরা ডেটাবেজে বসে থাকা একটি গণনা ক্ষেত্রটি যুক্ত করতে বা সরাতে পারি।
ফায়ার স্টোর ডকগুলি দেখুন - বিতরণ কাউন্টারগুলি বা জেফ ডেলানির ডেটা অগ্রিগেশনটি দেখুন । অ্যাঙ্গুলার ফায়ার ব্যবহার করা তার পক্ষে তার গাইডগুলি সত্যই দুর্দান্ত but তবে তার পাঠগুলি অন্য ফ্রেমওয়ার্কগুলিতেও বহন করা উচিত।
মেঘ ফাংশন:
export const documentWriteListener =
functions.firestore.document('collection/{documentUid}')
.onWrite((change, context) => {
if (!change.before.exists) {
// New document Created : add one to count
db.doc(docRef).update({numberOfDocs: FieldValue.increment(1)});
} else if (change.before.exists && change.after.exists) {
// Updating existing document : Do nothing
} else if (!change.after.exists) {
// Deleting document : subtract one from count
db.doc(docRef).update({numberOfDocs: FieldValue.increment(-1)});
}
return;
});
এখন আপনি ফ্রন্টএন্ডে সংগ্রহের আকারটি পেতে এই নম্বরঅফডকস ফিল্ডটিতে কোয়েরি করতে পারেন।
firestore.runTransaction { ... }
ব্লকে পঠন এবং লিখতে হবে । এটি অ্যাক্সেস সহ সম্মতি সংক্রান্ত সমস্যাগুলি সমাধান করে numberOfDocs
।
এটি করার সহজ উপায় হ'ল "ক্যোয়ারীস্ন্যাপশট" এর আকার পড়া।
db.collection("cities").get().then(function(querySnapshot) {
console.log(querySnapshot.size);
});
আপনি "ক্যোয়ারীস্ন্যাপশট" এর মধ্যেও ডক্স অ্যারের দৈর্ঘ্যটি পড়তে পারেন।
querySnapshot.docs.length;
অথবা যদি কোনও "ক্যোয়ারীস্ন্যাপশট" খালি মানটি পড়ে খালি হয়, যা একটি বুলিয়ান মান প্রদান করবে।
querySnapshot.empty;
db.collection.count()
। কেবল এগুলির জন্য তাদের বাদ দেওয়ার কথা ভাবছেন
যতদূর আমি জানি এটির জন্য কোনও বিল্ট-ইন সমাধান নেই এবং এটি এখনই নোড এসডকেই সম্ভব। যদি তোমার কাছে থাকে একটা
db.collection('someCollection')
তুমি ব্যবহার করতে পার
.select([fields])
আপনি কোন ক্ষেত্রটি নির্বাচন করতে চান তা নির্ধারণ করতে। আপনি যদি খালি নির্বাচন () করেন তবে আপনি কেবলমাত্র নথির রেফারেন্সের একটি অ্যারে পাবেন।
উদাহরণ:
db.collection('someCollection').select().get().then(
(snapshot) => console.log(snapshot.docs.length)
);
এই দ্রষ্টব্যটি সমস্ত দস্তাবেজগুলি ডাউনলোড করার জন্য সবচেয়ে খারাপ ক্ষেত্রে কেবলমাত্র একটি অপ্টিমাইজেশন এবং বড় সংগ্রহগুলিতে স্কেল করে না!
এছাড়াও এটি দেখুন:
ক্লাউড ফায়ার স্টোর সহ কোনও সংকলনে কীভাবে নথি সংখ্যা গণনা যায়
select(['_id'])
চেয়ে দ্রুতselect()
বড় সংগ্রহের জন্য নথি সংখ্যা গণনা সাবধান । আপনি যদি প্রতিটি সংকলনের জন্য পূর্বনির্ধারিত কাউন্টার রাখতে চান তবে ফায়ার স্টোর ডাটাবেসের সাথে এটি কিছুটা জটিল।
এই জাতীয় কোড এই ক্ষেত্রে কাজ করে না:
export const customerCounterListener =
functions.firestore.document('customers/{customerId}')
.onWrite((change, context) => {
// on create
if (!change.before.exists && change.after.exists) {
return firestore
.collection('metadatas')
.doc('customers')
.get()
.then(docSnap =>
docSnap.ref.set({
count: docSnap.data().count + 1
}))
// on delete
} else if (change.before.exists && !change.after.exists) {
return firestore
.collection('metadatas')
.doc('customers')
.get()
.then(docSnap =>
docSnap.ref.set({
count: docSnap.data().count - 1
}))
}
return null;
});
কারণ হ'ল প্রতিটি ক্লাউড ফায়ারস্টোর ট্রিগারকে আদর্শবান হতে হবে, যেমন ফায়ার স্টোর ডকুমেন্টেশন বলে: https://firebase.google.com/docs/funitions/firestore-events#limitations_and_guarantees
সুতরাং, আপনার কোডটির একাধিক মৃত্যুদণ্ড রোধ করার জন্য, আপনাকে ইভেন্ট এবং লেনদেনের সাহায্যে পরিচালনা করতে হবে। বৃহত সংগ্রহের কাউন্টারগুলি হ্যান্ডেল করার এটি আমার বিশেষ উপায়:
const executeOnce = (change, context, task) => {
const eventRef = firestore.collection('events').doc(context.eventId);
return firestore.runTransaction(t =>
t
.get(eventRef)
.then(docSnap => (docSnap.exists ? null : task(t)))
.then(() => t.set(eventRef, { processed: true }))
);
};
const documentCounter = collectionName => (change, context) =>
executeOnce(change, context, t => {
// on create
if (!change.before.exists && change.after.exists) {
return t
.get(firestore.collection('metadatas')
.doc(collectionName))
.then(docSnap =>
t.set(docSnap.ref, {
count: ((docSnap.data() && docSnap.data().count) || 0) + 1
}));
// on delete
} else if (change.before.exists && !change.after.exists) {
return t
.get(firestore.collection('metadatas')
.doc(collectionName))
.then(docSnap =>
t.set(docSnap.ref, {
count: docSnap.data().count - 1
}));
}
return null;
});
কেসগুলি এখানে ব্যবহার করুন:
/**
* Count documents in articles collection.
*/
exports.articlesCounter = functions.firestore
.document('articles/{id}')
.onWrite(documentCounter('articles'));
/**
* Count documents in customers collection.
*/
exports.customersCounter = functions.firestore
.document('customers/{id}')
.onWrite(documentCounter('customers'));
আপনি দেখতে পাচ্ছেন, একাধিক সম্পাদন রোধের মূল বিষয়টি প্রসঙ্গ অবজেক্টে ইভেন্টআইড নামে পরিচিত । যদি একই ইভেন্টের জন্য ফাংশনটি অনেক বার পরিচালনা করা হয় তবে ইভেন্টের আইডি সব ক্ষেত্রে একই হবে। দুর্ভাগ্যক্রমে, আপনার আপনার ডেটাবেজে "ইভেন্ট" সংগ্রহ থাকতে হবে।
context.eventId
একই ট্রিগারটির একাধিক অনুরোধে সর্বদা একই থাকবে? আমার পরীক্ষায় এটি সামঞ্জস্যপূর্ণ বলে মনে হয়, তবে আমি এটি উল্লেখ করে কোনও "অফিসিয়াল" ডকুমেন্টেশন খুঁজে পাই না।
2020 এ এটি এখনও ফায়ারবেস এসডিকে উপলভ্য নয় তবে এটি ফায়ারবেস এক্সটেনশনস (বিটা) এ পাওয়া যায় তবে এটি সেটআপ এবং ব্যবহার করা বেশ জটিল ...
একটি যুক্তিসঙ্গত পন্থা
সহায়কগণ ... (তৈরি / মুছে ফেলা অপ্রয়োজনীয় বলে মনে হয় তবে এটি অন-আপডেটের তুলনায় সস্তা)
export const onCreateCounter = () => async (
change,
context
) => {
const collectionPath = change.ref.parent.path;
const statsDoc = db.doc("counters/" + collectionPath);
const countDoc = {};
countDoc["count"] = admin.firestore.FieldValue.increment(1);
await statsDoc.set(countDoc, { merge: true });
};
export const onDeleteCounter = () => async (
change,
context
) => {
const collectionPath = change.ref.parent.path;
const statsDoc = db.doc("counters/" + collectionPath);
const countDoc = {};
countDoc["count"] = admin.firestore.FieldValue.increment(-1);
await statsDoc.set(countDoc, { merge: true });
};
export interface CounterPath {
watch: string;
name: string;
}
এক্সপোর্ট করা ফায়ার স্টোর হুকস
export const Counters: CounterPath[] = [
{
name: "count_buildings",
watch: "buildings/{id2}"
},
{
name: "count_buildings_subcollections",
watch: "buildings/{id2}/{id3}/{id4}"
}
];
Counters.forEach(item => {
exports[item.name + '_create'] = functions.firestore
.document(item.watch)
.onCreate(onCreateCounter());
exports[item.name + '_delete'] = functions.firestore
.document(item.watch)
.onDelete(onDeleteCounter());
});
কর্মে
বিল্ডিং রুট সংগ্রহ এবং সমস্ত উপ সংগ্রহগুলি ট্র্যাক করা হবে।
এখানে /counters/
মূল পাথের নিচে
এখন সংগ্রহের সংখ্যাগুলি স্বয়ংক্রিয়ভাবে এবং শেষ পর্যন্ত আপডেট হবে! আপনার যদি একটি গণনা প্রয়োজন, কেবল সংগ্রহের পথটি ব্যবহার করুন এবং এটির সাথে উপসর্গ করুন counters
।
const collectionPath = 'buildings/138faicnjasjoa89/buildingContacts';
const collectionCount = await db
.doc('counters/' + collectionPath)
.get()
.then(snap => snap.get('count'));
আমি @ মাতৃর সাথে একমত, আপনি যদি এই জাতীয় কোয়েরি করেন তবে অনেক খরচ হবে cost
[তাদের প্রকল্পগুলি শুরু করার আগে বিকাশকারীদের জন্য পরামর্শ]
যেহেতু আমরা শুরুতে এই পরিস্থিতিটি আগে থেকেই দেখেছি, আমরা প্রকৃতপক্ষে একটি ক্ষেত্রের মধ্যে সমস্ত কাউন্টারগুলিকে টাইপ করে সংরক্ষণ করার জন্য একটি নথি সহ একটি সংগ্রহ তৈরি করতে পারি number
।
উদাহরণ স্বরূপ:
সংগ্রহের প্রতিটি সিআরইউডি অপারেশনের জন্য, কাউন্টার ডকুমেন্টটি আপডেট করুন:
পরের বার, আপনি যখন সংগ্রহের সংখ্যা পেতে চান, আপনার কেবল ডকুমেন্টের ক্ষেত্রের দিকে প্রশ্ন / পয়েন্ট করতে হবে। [১ টি অপারেশন]
এছাড়াও, আপনি সংগ্রহের নাম একটি অ্যারেতে সঞ্চয় করতে পারেন, তবে এটি কৌশলটি জটিল হবে, ফায়ারবেসে অ্যারের শর্তটি নীচের মত দেখানো হয়েছে:
// we send this
['a', 'b', 'c', 'd', 'e']
// Firebase stores this
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e'}
// since the keys are numeric and sequential,
// if we query the data, we get this
['a', 'b', 'c', 'd', 'e']
// however, if we then delete a, b, and d,
// they are no longer mostly sequential, so
// we do not get back an array
{2: 'c', 4: 'e'}
সুতরাং, আপনি যদি সংগ্রহটি মুছে ফেলতে যাচ্ছেন না, আপনি প্রতিবার সমস্ত সংগ্রহ জিজ্ঞাসা না করে সংগ্রহের নামের তালিকা সংরক্ষণ করতে অ্যারে ব্যবহার করতে পারেন।
আশা করি এটা সাহায্য করবে!
না, এখনই একীকরণের প্রশ্নের জন্য কোনও অন্তর্নির্মিত সমর্থন নেই। তবে কয়েকটি জিনিস আপনি করতে পারেন।
প্রথম এখানে নথিভুক্ত করা হয় । আপনি সামগ্রিক তথ্য বজায় রাখতে লেনদেন বা মেঘ ফাংশন ব্যবহার করতে পারেন:
এই উদাহরণটি দেখায় যে উপ-সংগ্রহের পাশাপাশি গড় রেটিংয়ের রেটিংয়ের সংখ্যা ট্র্যাক রাখতে কোনও ফাংশন কীভাবে ব্যবহার করতে হয়।
exports.aggregateRatings = firestore
.document('restaurants/{restId}/ratings/{ratingId}')
.onWrite(event => {
// Get value of the newly added rating
var ratingVal = event.data.get('rating');
// Get a reference to the restaurant
var restRef = db.collection('restaurants').document(event.params.restId);
// Update aggregations in a transaction
return db.transaction(transaction => {
return transaction.get(restRef).then(restDoc => {
// Compute new number of ratings
var newNumRatings = restDoc.data('numRatings') + 1;
// Compute new average rating
var oldRatingTotal = restDoc.data('avgRating') * restDoc.data('numRatings');
var newAvgRating = (oldRatingTotal + ratingVal) / newNumRatings;
// Update restaurant info
return transaction.update(restRef, {
avgRating: newAvgRating,
numRatings: newNumRatings
});
});
});
});
আপনি যদি কেবলমাত্র নথিগুলি খুব কমই গণনা করতে চান তবে জেবিবি উল্লিখিত সমাধানটিও কার্যকর। select()
প্রতিটি নথির সমস্ত ডাউনলোড এড়ানোর জন্য বিবৃতিটি ব্যবহার নিশ্চিত করুন (এটি যখন আপনার কেবল একটি গণনার প্রয়োজন তখন এটি অনেকটা ব্যান্ডউইথ)। select()
কেবলমাত্র সার্ভার এসডিকেগুলিতে এখনই উপলভ্য যাতে সমাধানটি কোনও মোবাইল অ্যাপ্লিকেশনে কাজ করবে না।
সরাসরি কোনও বিকল্প উপলব্ধ নেই। আপনি করতে পারবেন না db.collection("CollectionName").count()
। নীচে দুটি উপায় যা দিয়ে আপনি সংগ্রহের মধ্যে নথির সংখ্যা গণনা করতে পারেন।
db.collection("CollectionName").get().subscribe(doc=>{
console.log(doc.size)
})
উপরের কোডটি ব্যবহার করে আপনার দস্তাবেজটি পড়তে হবে কোনও সংগ্রহের মধ্যে দস্তাবেজের আকারের সমান এবং সে কারণেই কোনও ব্যক্তিকে উপরের সমাধানটি ব্যবহার করা এড়াতে হবে।
db.collection("CollectionName").doc("counts")get().subscribe(doc=>{
console.log(doc.count)
})
উপরে আমরা সমস্ত গণনা তথ্য সংরক্ষণ করার জন্য নাম গণনা সহ একটি নথি তৈরি করেছি You আপনি নিম্নলিখিত উপায়ে গণনা ডকুমেন্টটি আপডেট করতে পারেন: -
আরআরটি দাম (ডকুমেন্ট রিড = 1) এবং দ্রুত ডেটা পুনরুদ্ধার উপরের সমাধানটি ভাল।
অ্যাডমিন.ফায়ার স্টোর.ফিল্ডভ্যালু.ইনক্রিমেন্ট ব্যবহার করে একটি কাউন্টার বাড়ান :
exports.onInstanceCreate = functions.firestore.document('projects/{projectId}/instances/{instanceId}')
.onCreate((snap, context) =>
db.collection('projects').doc(context.params.projectId).update({
instanceCount: admin.firestore.FieldValue.increment(1),
})
);
exports.onInstanceDelete = functions.firestore.document('projects/{projectId}/instances/{instanceId}')
.onDelete((snap, context) =>
db.collection('projects').doc(context.params.projectId).update({
instanceCount: admin.firestore.FieldValue.increment(-1),
})
);
এই উদাহরণে আমরা instanceCount
প্রতিটি instances
কালামে উপ-সংগ্রহে একটি ডকুমেন্ট যুক্ত হওয়ার পরে প্রকল্পের একটি ক্ষেত্র বৃদ্ধি করি । যদি ক্ষেত্রটি এখনও না থাকে তবে এটি তৈরি করা হবে এবং বাড়ানো হবে 1
ইনক্রিমেন্টেশন অভ্যন্তরীণভাবে লেনদেনের হয় তবে আপনার যদি প্রতি 1 সেকেন্ডের চেয়ে বেশি বার বার বৃদ্ধি প্রয়োজন হয় তবে আপনার বিতরণ কাউন্টারটি ব্যবহার করা উচিত ।
এটি প্রায়শই প্রয়োগ করা পছন্দনীয় onCreate
এবং onDelete
পরিবর্তে onWrite
আপনি onWrite
আপডেটগুলি কল করবেন যার অর্থ আপনি অপ্রয়োজনীয় ফাংশন আমন্ত্রণের জন্য বেশি অর্থ ব্যয় করছেন (যদি আপনি আপনার সংগ্রহে ডক্সগুলি আপডেট করেন)।
একটি কার্যনির্বাহীটি হ'ল:
ফায়ারবেস ডকটিতে একটি কাউন্টার লিখুন, যা আপনি প্রতিবার একটি নতুন এন্ট্রি তৈরির সময় লেনদেনের মধ্যে বৃদ্ধি করেন
আপনি আপনার নতুন প্রবেশের একটি ক্ষেত্রে গণনা সংরক্ষণ করুন (যেমন: অবস্থান: 4)।
তারপরে আপনি সেই ক্ষেত্রটিতে একটি সূচক তৈরি করুন (অবস্থান ডিইএসসি)।
আপনি একটি ক্যোয়ারী সহ একটি স্কিপ + সীমাবদ্ধতা করতে পারেন W যেখানে ("অবস্থান", "<" এক্স) rdআর্ডার বাই ("অবস্থান", ডিইএসসি)
আশাকরি এটা সাহায্য করবে!
আমি সমস্ত পাল্টা পরিস্থিতিগুলি (ক্যোয়ারী ব্যতীত) পরিচালনা করতে এই সমস্ত ধারণাগুলি ব্যবহার করে একটি সর্বজনীন ফাংশন তৈরি করেছি।
একমাত্র ব্যতিক্রম হ'ল যখন অনেকগুলি সেকেন্ড লেখেন তখন তা আপনাকে ধীর করে দেয়। একটি উদাহরণ ট্রেন্ডিং পোস্টে পছন্দ হবে । উদাহরণস্বরূপ এটি একটি ব্লগ পোস্টে ওভারকিল, এবং আপনার জন্য আরও বেশি ব্যয় হবে। আমি শারডগুলি ব্যবহার করে সেই ক্ষেত্রে একটি পৃথক ফাংশন তৈরি করার পরামর্শ দিচ্ছি: https://firebase.google.com/docs/firestore/solutions/counters
// trigger collections
exports.myFunction = functions.firestore
.document('{colId}/{docId}')
.onWrite(async (change: any, context: any) => {
return runCounter(change, context);
});
// trigger sub-collections
exports.mySubFunction = functions.firestore
.document('{colId}/{docId}/{subColId}/{subDocId}')
.onWrite(async (change: any, context: any) => {
return runCounter(change, context);
});
// add change the count
const runCounter = async function (change: any, context: any) {
const col = context.params.colId;
const eventsDoc = '_events';
const countersDoc = '_counters';
// ignore helper collections
if (col.startsWith('_')) {
return null;
}
// simplify event types
const createDoc = change.after.exists && !change.before.exists;
const updateDoc = change.before.exists && change.after.exists;
if (updateDoc) {
return null;
}
// check for sub collection
const isSubCol = context.params.subDocId;
const parentDoc = `${countersDoc}/${context.params.colId}`;
const countDoc = isSubCol
? `${parentDoc}/${context.params.docId}/${context.params.subColId}`
: `${parentDoc}`;
// collection references
const countRef = db.doc(countDoc);
const countSnap = await countRef.get();
// increment size if doc exists
if (countSnap.exists) {
// createDoc or deleteDoc
const n = createDoc ? 1 : -1;
const i = admin.firestore.FieldValue.increment(n);
// create event for accurate increment
const eventRef = db.doc(`${eventsDoc}/${context.eventId}`);
return db.runTransaction(async (t: any): Promise<any> => {
const eventSnap = await t.get(eventRef);
// do nothing if event exists
if (eventSnap.exists) {
return null;
}
// add event and update size
await t.update(countRef, { count: i });
return t.set(eventRef, {
completed: admin.firestore.FieldValue.serverTimestamp()
});
}).catch((e: any) => {
console.log(e);
});
// otherwise count all docs in the collection and add size
} else {
const colRef = db.collection(change.after.ref.parent.path);
return db.runTransaction(async (t: any): Promise<any> => {
// update size
const colSnap = await t.get(colRef);
return t.set(countRef, { count: colSnap.size });
}).catch((e: any) => {
console.log(e);
});;
}
}
এটি ইভেন্ট, ইনক্রিমেন্ট এবং লেনদেন পরিচালনা করে। এর সৌন্দর্যটি হ'ল আপনি যদি কোনও নথির যথার্থতা সম্পর্কে নিশ্চিত না হন (সম্ভবত বিটা থাকাকালীনও), আপনি পরবর্তী কাউকে এটি স্বয়ংক্রিয়ভাবে পরবর্তী ট্রিগারটিতে যুক্ত করার জন্য কাউন্টারটি মুছতে পারেন। হ্যাঁ, এই ব্যয়গুলি, তাই অন্যথায় এটি মুছবেন না।
গণনা পেতে একই ধরণের জিনিস:
const collectionPath = 'buildings/138faicnjasjoa89/buildingContacts';
const colSnap = await db.doc('_counters/' + collectionPath).get();
const count = colSnap.get('count');
এছাড়াও, আপনি ডাটাবেস স্টোরেজে অর্থ সাশ্রয়ের জন্য পুরানো ইভেন্টগুলি সরাতে ক্রোন জব (নির্ধারিত ফাংশন) তৈরি করতে চাইতে পারেন। আপনার কমপক্ষে একটি জ্বলন পরিকল্পনা দরকার এবং আরও কিছু কনফিগারেশন থাকতে পারে। উদাহরণস্বরূপ, আপনি প্রতি রবিবার এগারোটায় এটি চালাতে পারেন। https://firebase.google.com/docs/functions/schedule-functions
এটি অনির্ধারিত , তবে কয়েকটি টুইটের সাথে কাজ করা উচিত:
exports.scheduledFunctionCrontab = functions.pubsub.schedule('5 11 * * *')
.timeZone('America/New_York')
.onRun(async (context) => {
// get yesterday
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
const eventFilter = db.collection('_events').where('completed', '<=', yesterday);
const eventFilterSnap = await eventFilter.get();
eventFilterSnap.forEach(async (doc: any) => {
await doc.ref.delete();
});
return null;
});
এবং সর্বশেষে, ফায়ারস্টোর.রুলসগুলিতে সংগ্রহগুলি সুরক্ষিত করতে ভুলবেন না :
match /_counters/{document} {
allow read;
allow write: if false;
}
match /_events/{document} {
allow read, write: if false;
}
আপডেট: ক্যোয়ারী
আমার অন্যান্য উত্তরে যুক্ত করা আপনি যদি ক্যোয়ারী গণনাগুলিকেও স্বয়ংক্রিয় করতে চান তবে আপনি নিজের ক্লাউড ফাংশনে এই সংশোধিত কোডটি ব্যবহার করতে পারেন:
if (col === 'posts') {
// counter reference - user doc ref
const userRef = after ? after.userDoc : before.userDoc;
// query reference
const postsQuery = db.collection('posts').where('userDoc', "==", userRef);
// add the count - postsCount on userDoc
await addCount(change, context, postsQuery, userRef, 'postsCount');
}
return delEvents();
যা ইউজার ডকুমেন্টে পোস্টসাউন্টটি স্বয়ংক্রিয়ভাবে আপডেট হবে । আপনি সহজেই অন্য কাউকে এইভাবে অনেকগুলি সংখ্যায় যুক্ত করতে পারেন। এটি আপনাকে কীভাবে জিনিসগুলিকে স্বয়ংক্রিয় করতে পারে তার ধারণা দেয়। ইভেন্টগুলি মুছে ফেলার জন্য আমি আপনাকে আরও একটি উপায় দিয়েছি। মুছে ফেলার জন্য আপনাকে প্রতিটি তারিখটি পড়তে হবে, সুতরাং এটি পরে মুছে ফেলার জন্য আপনাকে সত্যিকার অর্থে সংরক্ষণ করবে না, কেবল ফাংশনটি ধীর করে দেবে।
/**
* Adds a counter to a doc
* @param change - change ref
* @param context - context ref
* @param queryRef - the query ref to count
* @param countRef - the counter document ref
* @param countName - the name of the counter on the counter document
*/
const addCount = async function (change: any, context: any,
queryRef: any, countRef: any, countName: string) {
// events collection
const eventsDoc = '_events';
// simplify event type
const createDoc = change.after.exists && !change.before.exists;
// doc references
const countSnap = await countRef.get();
// increment size if field exists
if (countSnap.get(countName)) {
// createDoc or deleteDoc
const n = createDoc ? 1 : -1;
const i = admin.firestore.FieldValue.increment(n);
// create event for accurate increment
const eventRef = db.doc(`${eventsDoc}/${context.eventId}`);
return db.runTransaction(async (t: any): Promise<any> => {
const eventSnap = await t.get(eventRef);
// do nothing if event exists
if (eventSnap.exists) {
return null;
}
// add event and update size
await t.set(countRef, { [countName]: i }, { merge: true });
return t.set(eventRef, {
completed: admin.firestore.FieldValue.serverTimestamp()
});
}).catch((e: any) => {
console.log(e);
});
// otherwise count all docs in the collection and add size
} else {
return db.runTransaction(async (t: any): Promise<any> => {
// update size
const colSnap = await t.get(queryRef);
return t.set(countRef, { [countName]: colSnap.size }, { merge: true });
}).catch((e: any) => {
console.log(e);
});;
}
}
/**
* Deletes events over a day old
*/
const delEvents = async function () {
// get yesterday
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
const eventFilter = db.collection('_events').where('completed', '<=', yesterday);
const eventFilterSnap = await eventFilter.get();
eventFilterSnap.forEach(async (doc: any) => {
await doc.ref.delete();
});
return null;
}
আমার এও আপনাকে সতর্ক করে দেওয়া উচিত যে সর্বজনীন ফাংশন প্রতিটি অনরাইট কল পিরিয়ডে চলবে। কেবলমাত্র অনক্রিট এবং আপনার নির্দিষ্ট সংগ্রহের অনডিলিট ইভেন্টগুলিতে ফাংশনটি চালানো সস্তা হবে। আমরা যে এনএসকিউএল ডাটাবেসটি ব্যবহার করছি তার মতো, বারবার কোড এবং ডেটা আপনার অর্থ সাশ্রয় করতে পারে।
উপরের কয়েকটি উত্তরের উপর ভিত্তি করে এই কাজটি করতে আমাকে কিছুটা সময় নিয়েছে, তাই আমি ভেবেছিলাম এটি অন্যের ব্যবহারের জন্য ভাগ করে নেব। আমি আশা করি এটি কার্যকর
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
exports.countDocumentsChange = functions.firestore.document('library/{categoryId}/documents/{documentId}').onWrite((change, context) => {
const categoryId = context.params.categoryId;
const categoryRef = db.collection('library').doc(categoryId)
let FieldValue = require('firebase-admin').firestore.FieldValue;
if (!change.before.exists) {
// new document created : add one to count
categoryRef.update({numberOfDocs: FieldValue.increment(1)});
console.log("%s numberOfDocs incremented by 1", categoryId);
} else if (change.before.exists && change.after.exists) {
// updating existing document : Do nothing
} else if (!change.after.exists) {
// deleting document : subtract one from count
categoryRef.update({numberOfDocs: FieldValue.increment(-1)});
console.log("%s numberOfDocs decremented by 1", categoryId);
}
return 0;
});
আমি বিভিন্ন পদ্ধতির সাথে অনেক চেষ্টা করেছি। এবং পরিশেষে, আমি একটি পদ্ধতির উন্নতি করি। প্রথমে আপনাকে একটি পৃথক সংগ্রহ তৈরি করতে হবে এবং সেখানে সমস্ত ইভেন্ট সংরক্ষণ করতে হবে। দ্বিতীয়ত আপনাকে সময় দ্বারা ট্রিগার করার জন্য একটি নতুন ল্যাম্বডা তৈরি করতে হবে। এই ল্যাম্বদা ইভেন্ট সংগ্রহ এবং ইভেন্টের দস্তাবেজগুলিতে ইভেন্টগুলি গণনা করবে। নিবন্ধে কোড বিশদ। https://medium.com/@ihor.malaniuk/how-to-count-documents-in-google-cloud-firestore-b0e65863aeca
এই ক্যোয়ারির ফলে নথির গণনা হবে।
this.db.collection(doc).get().subscribe((data) => {
count = data.docs.length;
});
console.log(count)
এটি সংখ্যার অনন্য আইডি তৈরি করতে গণনা ব্যবহার করে। আমার ব্যবহারে, আমি কখনই হ্রাস পাচ্ছি না , এমনকি document
আইডিটি মুছে ফেলা হলেও।
এমন এক collection
ক্রিয়েশনের জন্য যার অনন্য সংখ্যার মান প্রয়োজন needs
appData
এক নথিতে সঙ্গে, set
সঙ্গে .doc
আইডিonly
uniqueNumericIDAmount
মধ্যে 0 তে করুনfirebase firestore console
doc.data().uniqueNumericIDAmount + 1
অনন্য সংখ্যা আইডি হিসাবেappData
সংগ্রহ আপডেট করুনuniqueNumericIDAmount
firebase.firestore.FieldValue.increment(1)
firebase
.firestore()
.collection("appData")
.doc("only")
.get()
.then(doc => {
var foo = doc.data();
foo.id = doc.id;
// your collection that needs a unique ID
firebase
.firestore()
.collection("uniqueNumericIDs")
.doc(user.uid)// user id in my case
.set({// I use this in login, so this document doesn't
// exist yet, otherwise use update instead of set
phone: this.state.phone,// whatever else you need
uniqueNumericID: foo.uniqueNumericIDAmount + 1
})
.then(() => {
// upon success of new ID, increment uniqueNumericIDAmount
firebase
.firestore()
.collection("appData")
.doc("only")
.update({
uniqueNumericIDAmount: firebase.firestore.FieldValue.increment(
1
)
})
.catch(err => {
console.log(err);
});
})
.catch(err => {
console.log(err);
});
});
firebaseFirestore.collection("...").addSnapshotListener(new EventListener<QuerySnapshot>() {
@Override
public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
int Counter = documentSnapshots.size();
}
});