我已经阅读了关于随机 java、swift 但 JS 随机文档 firestore 的文档,我找不到,我发现这个问题还没有出现在 JS 上?
迅速
postsRef.whereField("random", isGreaterThanOrEqualTo: random)
.order(by: "random")
.limit(to: 1)
JS
postsRef.where("random", ">=", random)
.order("random")
.limit(1)
这是正确的吗?
答案 0 :(得分:2)
Typescript(如果使用 Javascript,请删除类型)版本,用于使用随机整数(和环绕)获取随机文档。此答案使用 Cloud 函数进行测试,但本质上您只需要复制 getDocuments
函数。
export const getRandomDoc = functions.https.onRequest(async (req, res): Promise<any> => {
try {
const randomDocs = await getDocuments(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) {
return getDocuments(count)
}
return snapshot.docs.map(d => d.data())
}
每当您向该集合添加新文档时,请同时添加 rInt
字段,该字段是 0 到 10000(包括两者)之间的整数。您在 getDoucments
函数中传递所需的文档数量。它将获取 N 个连续匹配的文档,因为它使用 limit()
方法。
在查询中,我们查找 rInt
大于或等于使用 Math.random()
生成的随机数的文档,并将结果限制为函数中传递的 count
参数。如果快照为空,我们重试该函数。 (值得添加一个逻辑,使此函数仅重复 N 次,否则递归将花费时间)。
在上面的函数中使用 .limit()
将最终连续返回 N 个文档。默认情况下,文档将按文档 ID 排序,除非您使用 orderBy
方法指定任何特定字段。相反,为每个文档单独提出请求会增加随机性。
/**
* @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 documents
const requests = []
for (let i = 0; i < count; i++) {
// New random number for each request
const 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 promises
const snapshots = await Promise.all(requests)
// Removing empty snapshots
const filteredSnapshots = snapshots.filter(d => !d.empty)
// Creating an array of doc data
const matchedDocs = filteredSnapshots.map(doc => doc.docs[0].data())
// If documents received are less than requested,
// repeat the function
if (matchedDocs.length !== count) {
// If the function is repeated 5 times,
// return with whatever has matched so far
if (loopNum + 1 === 5) {
console.log("Returning CurDocs")
return curDocs
}
return getDocuments(count, loopNum + 1, [...curDocs, ...matchedDocs])
}
// Return if you get requested num of docs in first go
return snapshots.map(d => d.docs[0].data())
}
// Calling the function
getDocuments(5, 0, [])
请注意,如果您请求的文档少于或等于 10 个,则可以使用 in
运算符。 in 运算符将同一字段上的最多 10 个等式 (==) 子句与逻辑 OR 组合在一起。
对于 @Dan McGrath, check this answer 的原始版本 (swift)。