Firestore-如何确定地从集合中获取多个随机(非重复,特定数量的)文档? [英] Firestore - How to get multiple random (non duplicated, specific number of) documents from a collection with certainty?

查看:41
本文介绍了Firestore-如何确定地从集合中获取多个随机(非重复,特定数量的)文档?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用来自 https://stackoverflow.com/a/46801925/3073280 的Dan McGrath的解决方案(生成和查询随机索引),只要集合中有一个或多个文档,我就可以肯定地得到一个随机文档.换句话说,获取一个随机文档很容易.

Using Dan McGrath's solution from https://stackoverflow.com/a/46801925/3073280 (to generate and query random indexes), I can certainly and definitely get one random document whenever the collection has one or more documents. Put another way, getting one random document is easy.

但是,我很难实施Dan McGrath的解决方案来确定地从集合中获取多个随机(非重复)文档.我指的是Dan McGrath的冲洗和重复溶液.

But, I have difficulty in implementing Dan McGrath's solution to get multiple random (non-duplicated) documents from a collection with certainty. I am referring to Dan McGrath’s rinse and repeat solution.

因此,参考下面的伪代码,当集合中有5个文档时,如何随机准确地获取3个文档*(非重复)?

So, with reference to my pseudo code below, how to get exactly 3 documents* (non duplicated) at random when the collection has 5 documents?

import { Component, OnInit } from '@angular/core';

import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/firestore';
import { throwError, interval, of }  from 'rxjs';
import { retry, switchMap, mergeMap, take } from 'rxjs/operators';


@Component({
  selector: 'app-firestore',
  templateUrl: './firestore.component.html',
  styleUrls: ['./firestore.component.css']
})
export class FirestoreComponent implements OnInit {

  constructor(private afs: AngularFirestore) {

  } 

  // This is the sample data structure in Firestore with only 5 documents in the collection
  // -Collection name is testRandom
  // --Document Auto ID
  // --- { random: 1 }
  // --Document Auto ID
  // --- { random: 2 }
  // --Document Auto ID
  // --- { random: 4, remark: 'intentionally skip 3' }
  // --Document Auto ID
  // --- { random: 5 }
  // --Document Auto ID
  // --- { random: 7, remark: 'intentionally skip 6' }

  getRandomIntInclusive(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min + 1) + min); //The maximum is inclusive and the minimum is inclusive
  }

  /*
  * This will return one document at random but this will not guarantee return if the random number is 3 or 6
  * */
  selectSingleRandomDocument_byQueryingRandomIndexes() {
    return this.afs.collection<Item>('testRandom',
        ref => ref.where('random', '==', this.getRandomIntInclusive(1,7)).limit(1)
    )
      .valueChanges()
      .pipe(
        mergeMap(doc => {
          if (doc.length > 0) {
            return of(doc);
          } else {
            return throwError('no random document queried because the random number is either 3 or 6, hence throw error so it will retry')
          }
        }),
      )
  }

  /*
  * This will query for 3 documents but it will not guarantee return 3 documents if error thrown
  * */
  rinseAndRepeat() {
    interval(2000)
      .pipe(
        take(3),
        switchMap(val => this.selectSingleRandomDocument_byQueryingRandomIndexes()
            .pipe(retry(5)) // return 5 times if get throwError from singleRandomDocument
        )
      )
      .subscribe();
  }

}

总之,当集合有5个文档时,如何随机准确地获取3个文档*(非重复)?

In brief, how to get exactly 3 documents* (non duplicated) at random when the collection has 5 documents?

*注:在生产中,它将从一个集合中的数千个文档中随机查询80个文档;因此,请不要建议阅读整个文档集并随机洗排文档,然后再阅读前80个文档.

*Note: In production, it would query for 80 documents at random out of thousands of documents from a collection; hence, please do not suggest reading the whole collection and shuffle the documents randomly then read the top 80 documents.

推荐答案

似乎就像在查询之前检查随机int以确保它们唯一一样简单.在响应中可能有更优雅的方法来实现此目的,但这似乎是可行的.

It seems like it would be as simple as checking the random ints to ensure they are unique before querying. There are probably more elegant ways to achieve this in react, but this seems like it would work.

getSetOfRandomInts(num) {
   const set = new Set();
   while(set.size < num) { // retry if we get dups
     set.add(this.getRandomIntInclusive(1,7));
   }
   return set;
}

selectSingleDocumentByRandomIndex(randomNumber) {
    return this.afs.collection<Item>('testRandom',
        ref => ref.where('random', '==', randomNumber).limit(1)
    )
      .valueChanges()
      .pipe(
        mergeMap(doc => {
          if (doc.length > 0) {
            return of(doc);
          } else {
            return throwError('no random document queried because the random number is either 3 or 6, hence throw error so it will retry')
          }
        }),
      )
  }

rinseAndRepeat() {
    interval(2000)
      .pipe(
        () => this.getSetOfRandomInts(3),
        switchMap(randomInt => this.selectSingleDocumentByRandomIndex(randomInt)
            .pipe(retry(5))
        )
      )
      .subscribe();
  }

这篇关于Firestore-如何确定地从集合中获取多个随机(非重复,特定数量的)文档?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆