Get Random Documents From Firestore Using Javascript
Solution 1:
Typescript (remove the types if you use Javascript) version for getting random documents using random integers (and wrap-around). This answer uses Cloud function for testing but essentially you just need to copy the getDocuments
function.
exportconst getRandomDoc = functions.https.onRequest(async (req, res): Promise<any> => {
try {
const randomDocs = awaitgetDocuments(2)
return res.send(randomDocs)
} catch (err) {
return res.send(err)
}
});
const getDocuments = async (count: number): Promise<Array<FirebaseFirestore.DocumentData>> => {
const randomNum = Math.floor(Math.random() * 10000)
const snapshot = await admin.firestore().collection("col").where("rInt", ">=", randomNum).limit(count).get()
if (snapshot.empty) {
returngetDocuments(count)
}
return snapshot.docs.map(d => d.data())
}
Whenever you add a new document to that collection, add the rInt
field along with it which is an integer between 0 to 10000 (both inclusive). You pass the number of documents you need in the getDoucments
function. It will fetch N consecutive matched docs though as this uses limit()
method.
In the query we look for documents where rInt
is greater than or equal to that random number generated using Math.random()
and limit the results to count
parameter passed in the function. If the snapshot is empty we retry the function. (It'll be worth to add a logic which makes this function repeat only N number of time else recursion will take it's time).
Using .limit()
as in the function above will end up returning N documents in a row. By default, docs will be ordered by their document ID unless you specify any particular field using orderBy
method. Instead making a separate request for each doc will increase the randomicity.
/**
* @param {number} count - number of documents to retrieve
* @param {number} loopNum - number of times the loop is being repeated. Defaults to 0
* @param {Array<any>} curDocs - array of documents matched so far. Defaults to an empty array
* @returns
*/const getDocuments = async (count: number, loopNum: number, curDocs: Array<any>): Promise<Array<FirebaseFirestore.DocumentData>> => {
// Creating an array of requests to get documentsconst requests = []
for (let i = 0; i < count; i++) {
// New random number for each requestconst randomNum = Math.floor(Math.random() * 10000)
console.log(`Random Num: ${randomNum}`);
requests.push(admin.firestore().collection("col").where("rInt", ">=", randomNum).limit(1).get())
// limit is set to 1 so each request will return 1 document only
}
// Using Promise.all() to run all the promisesconst snapshots = awaitPromise.all(requests)
// Removing empty snapshotsconst filteredSnapshots = snapshots.filter(d => !d.empty)
// Creating an array of doc dataconst matchedDocs = filteredSnapshots.map(doc => doc.docs[0].data())
// If documents received are less than requested,// repeat the functionif (matchedDocs.length !== count) {
// If the function is repeated 5 times,// return with whatever has matched so farif (loopNum + 1 === 5) {
console.log("Returning CurDocs")
return curDocs
}
returngetDocuments(count, loopNum + 1, [...curDocs, ...matchedDocs])
}
// Return if you get requested num of docs in first goreturn snapshots.map(d => d.docs[0].data())
}
// Calling the functiongetDocuments(5, 0, [])
Do note that you can use in
operator if you are requesting less than or equal to 10 documents. The in operator combines up to 10 equality (==) clauses on the same field with a logical OR.
For original version (swift) by @Dan McGrath, check this answer.
Post a Comment for "Get Random Documents From Firestore Using Javascript"