소방서:컬렉션에서 임의의 문서를 가져오는 방법
내 애플리케이션은 파이어베이스의 컬렉션에서 여러 문서를 무작위로 선택할 수 있는 것이 중요합니다.
Firebase에는 이를 수행하는 쿼리를 수행하기 위한 기본 함수가 내장되어 있지 않으므로, 첫 번째 생각은 컬렉션에 있는 문서 수가 있는 경우 쿼리 커서를 사용하여 임의의 시작 및 종료 인덱스를 선택하는 것이었습니다.
이 접근 방식은 모든 문서가 항상 인접 문서와 순서대로 제공되기 때문에 제한된 방식으로만 작동합니다.상위 컬렉션에서 인덱스를 사용하여 문서를 선택할 수 있다면 랜덤 문서 쿼리를 수행할 수 있지만 문제는 사용자가 이 작업을 수행하는 방법을 설명하는 문서를 찾을 수 없다는 것입니다.
다음과 같은 Firestore 스키마를 고려해 보겠습니다.
root/
posts/
docA
docB
docC
docD
그런 다음 고객(Swift 환경에 있음)에서 다음과 같은 작업을 수행할 수 있는 쿼리를 작성하려고 합니다.
db.collection("posts")[0, 1, 3] // would return: docA, docB, docD
제가 이것과 같은 방법으로 뭔가를 할 수 있는 방법이 있을까요?아니면 비슷한 방식으로 임의의 문서를 선택할 수 있는 다른 방법이 있습니까?
제발 도와주세요.
임의로 생성된 인덱스와 간단한 쿼리를 사용하여 Cloud Firestore의 컬렉션 또는 컬렉션 그룹에서 문서를 임의로 선택할 수 있습니다.
이 답변은 4개의 섹션으로 나뉘며 각 섹션마다 다른 옵션이 있습니다.
- 임의 인덱스 생성 방법
- 임의 인덱스를 쿼리하는 방법
- 여러 임의 문서 선택
- 진행 중인 무작위성을 위해 재시딩
임의 인덱스 생성 방법
이 답변의 기본은 색인 필드를 만드는 것입니다. 색인 필드는 오름차순 또는 내림차순으로 정렬하면 모든 문서가 임의로 정렬됩니다.이를 생성하는 방법은 여러 가지가 있으므로 가장 쉽게 사용할 수 있는 방법부터 시작하여 2가지를 살펴보겠습니다.
자동 ID 버전
클라이언트 라이브러리에 제공된 임의로 생성된 자동 ID를 사용하는 경우 동일한 시스템을 사용하여 문서를 임의로 선택할 수 있습니다.이 경우 랜덤하게 정렬된 인덱스는 문서 ID입니다.
나중에 쿼리 섹션에서 생성하는 임의의 값은 새로운 자동 ID(iOS, Android, Web)이며 쿼리하는 필드는__name__필드이며, 나중에 언급된 '낮은 값'은 빈 문자열입니다.이것은 랜덤 인덱스를 생성하는 가장 쉬운 방법이며 언어와 플랫폼에 관계없이 작동합니다.
기본적으로 문서 이름(__name__는 색인화된 이며, 및 다시 을 바꿀 수 .는 색인화된 오름차순이며, 삭제하고 다시 작성하지 않으면 기존 문서의 이름을 바꿀 수 없습니다.중 하다면 이 하 나 가 필 한 도 사 실 ID 필 로 저 수 있 니 습 할 장 드 제 같 은 과 다 음 자 동 여 하 경 요 용random이 목적을 위해 문서 이름을 오버로드하는 것보다.
임의 정수 버전
하여 문를작성때, 먼범서임정의에위할생라는 합니다.random예상되는 문서 수에 따라 다른 경계 범위를 사용하여 공간을 절약하거나 충돌 위험을 줄일 수 있습니다(이 방법의 효과를 감소시킵니다).
다른 고려 사항이 있을 것이므로 필요한 언어를 고려해야 합니다.Swift는 쉽지만 JavaScript는 특히 Gotcha를 사용할 수 있습니다.
이렇게 하면 문서가 임의로 정렬된 색인이 만들어집니다.나중에 쿼리 섹션에서 생성하는 임의의 값은 이러한 값 중 하나가 되고 나중에 언급되는 '낮은 값'은 -1이 됩니다.
임의 인덱스를 쿼리하는 방법
이제 랜덤 인덱스가 생겼으니 쿼리를 수행해야 합니다.아래에서는 임의의 문서 1개를 선택하기 위한 몇 가지 간단한 변형과 1개 이상을 선택하기 위한 옵션을 살펴봅니다.
옵션에 할 때 할 수 이 " 러한모옵경우인, 값문를형동있다수니습변식"로 됩니다.random이 값을 사용하여 인덱스에서 임의의 지점을 찾습니다.
랩어라운드
이제 임의의 값을 갖게 되었으므로 단일 문서에 대해 쿼리할 수 있습니다.
let postsRef = db.collection("posts")
queryRef = postsRef.whereField("random", isGreaterThanOrEqualTo: random)
.order(by: "random")
.limit(to: 1)
문서가 반환되었는지 확인합니다.그렇지 않은 경우 다시 쿼리하지만 임의 인덱스에 대해 '낮은 값'을 사용합니다.예를 들어, 랜덤 정수를 수행한 경우lowValue이라0:
let postsRef = db.collection("posts")
queryRef = postsRef.whereField("random", isGreaterThanOrEqualTo: lowValue)
.order(by: "random")
.limit(to: 1)
하나의 문서가 있는 한, 적어도 하나의 문서를 반환해야 합니다.
양방향
축소 방법은 구현이 간단하며 오름차순 인덱스만 활성화하여 스토리지를 최적화할 수 있습니다.한 가지 단점은 가치가 부당하게 차폐될 가능성입니다.예를 들어, 10K 중 처음 3개 문서(A,B,C)의 인덱스 값이 A:409496, B:436496, C:818992인 경우, A와 C가 선택될 확률은 1/10K 미만인 반면, B는 A의 근접성과 약 1/160K의 확률로 효과적으로 차폐됩니다.
때을 하는 할 수 .>=그리고.<=이는 인덱스 스토리지의 두 배에 달하는 비용으로 부당하게 차폐된 값의 확률을 절반으로 줄입니다.
한 방향이 결과를 반환하지 않으면 다른 방향으로 전환합니다.
queryRef = postsRef.whereField("random", isLessThanOrEqualTo: random)
.order(by: "random", descending: true)
.limit(to: 1)
queryRef = postsRef.whereField("random", isGreaterThanOrEqualTo: random)
.order(by: "random")
.limit(to: 1)
여러 임의 문서 선택
한 번에 둘 이상의 임의 문서를 선택하려는 경우가 많습니다.원하는 절충안에 따라 위의 기술을 조정하는 방법은 두 가지가 있습니다.
헹군 후 반복
이 방법은 간단합니다.매번 새로운 랜덤 정수를 선택하는 것을 포함하여 이 과정을 반복합니다.
이 방법은 동일한 패턴을 반복적으로 볼 걱정 없이 문서의 임의 시퀀스를 제공합니다.
단점은 각 문서에 대해 별도의 서비스 왕복이 필요하기 때문에 다음 방법보다 속도가 느려진다는 것입니다.
계속 오게 해.
이 방법에서는 원하는 문서의 제한 수를 늘리기만 하면 됩니다.당신이 돌아올 수도 있기 때문에 조금 더 복잡합니다.0..limit통화 중인 문서입니다.그런 다음 누락된 문서를 동일한 방법으로 가져오되, 차이로만 제한을 줄여야 합니다.요청한 문서 수보다 총 문서 수가 더 많다는 것을 알고 있는 경우, 두 번째 호출(첫 번째 호출은 아님)에서 충분한 문서를 받지 못하는 에지 케이스를 무시하여 최적화할 수 있습니다.
이 솔루션과의 절충은 반복적인 순서로 이루어집니다.문서가 임의로 정렬되어 있는 동안 범위가 중복되면 이전에 본 것과 동일한 패턴을 볼 수 있습니다.리시딩에 대한 다음 섹션에서 이 문제를 완화할 수 있는 방법이 설명되어 있습니다.
이 접근 방식은 'Rins & Repeat'보다 빠릅니다. 최상의 경우 한 번의 통화 또는 최악의 경우 2번의 통화로 모든 문서를 요청할 수 있기 때문입니다.
진행 중인 무작위성을 위해 재시딩
이 방법은 문서 집합이 정적인 경우 임의로 문서를 제공하지만 각 문서가 반환될 확률도 정적입니다.이는 일부 값이 초기 랜덤 값에 따라 부당하게 낮거나 높은 확률을 가질 수 있기 때문에 문제가 됩니다.대부분의 사용 사례에서 이것은 괜찮지만, 일부 사용 사례에서는 하나의 문서를 반환할 가능성이 더 균일하도록 장기 랜덤성을 증가시킬 수 있습니다.
삽입된 문서는 중간에 꼬여 점차 문서를 삭제하고 확률을 변경합니다.문서 수를 고려할 때 삽입/삭제 비율이 너무 작으면 이를 해결하는 몇 가지 전략이 있습니다.
다중 랜덤
재시딩을 걱정하지 않고 문서당 여러 개의 임의 인덱스를 작성한 후 매번 해당 인덱스 중 하나를 임의로 선택할 수 있습니다.를 들어,는 " " " ", " " 입니다.random map 1 ~ 예를 들어 1~3은 다음과 같습니다.
{'random': {'1': 32456, '2':3904515723, '3': 766958445}}
이제 랜덤.1, 랜덤.2, 랜덤.3에 대해 랜덤하게 쿼리를 수행하여 랜덤성의 범위를 넓힙니다.이는 기본적으로 증가된 스토리지를 교환하여 재시딩해야 하는 증가된 컴퓨팅(문서 쓰기)을 절약합니다.
쓰기 시 다시 시드
" " " " " " " 의 random필드입니다. 이렇게 하면 문서가 임의 인덱스로 이동합니다.
읽기 시 다시 시드
생성된 랜덤 값이 균일하게 분포되지 않은 경우(랜덤 값이므로 예상됨) 동일한 문서가 부적절한 시간 동안 선택될 수 있습니다.이것은 무작위로 선택된 문서를 읽은 후 새로운 무작위 값으로 업데이트하면 쉽게 대응할 수 있습니다.
는 더 핫스팟을 사용할 수 에 읽기할 수 쓰는더비 핫고될예때수에문있이당,시부읽때을만도선업수록하데있이다트택,니신은의집합분할을습간기기싸스팟예▁since▁on▁read,▁of▁a(e다▁you있니).if random(0,100) === 0) update;).
앞으로 이 문제가 발생하는 모든 사람을 돕기 위해 이 글을 게시합니다.
자동 ID를 사용하는 경우 새 자동 ID를 생성하고 Dan McGrath's Answer에 언급된 대로 가장 가까운 자동 ID를 쿼리할 수 있습니다.
저는 최근에 랜덤 견적 api를 만들었고 소방서 컬렉션에서 랜덤 견적을 받아야 했습니다.
이것이 제가 그 문제를 해결한 방법입니다.
var db = admin.firestore();
var quotes = db.collection("quotes");
var key = quotes.doc().id;
quotes.where(admin.firestore.FieldPath.documentId(), '>=', key).limit(1).get()
.then(snapshot => {
if(snapshot.size > 0) {
snapshot.forEach(doc => {
console.log(doc.id, '=>', doc.data());
});
}
else {
var quote = quotes.where(admin.firestore.FieldPath.documentId(), '<', key).limit(1).get()
.then(snapshot => {
snapshot.forEach(doc => {
console.log(doc.id, '=>', doc.data());
});
})
.catch(err => {
console.log('Error getting documents', err);
});
}
})
.catch(err => {
console.log('Error getting documents', err);
});
쿼리의 핵심은 다음과 같습니다.
.where(admin.firestore.FieldPath.documentId(), '>', key)
그리고 문서가 발견되지 않으면 작업이 취소된 상태에서 다시 호출합니다.
이것이 도움이 되길 바랍니다!
방금 Angular 7 + RxJS에서 이 작업을 만들었습니다. 그래서 예시를 원하는 사람들과 여기서 공유합니다.
@Dan McGrath의 답변을 사용하여 여러 숫자에 대해 랜덤 정수 버전 + 린스 및 반복 옵션을 선택했습니다.저는 또한 이 기사에서 설명한 것을 사용했습니다: RxJS, If-Else 연산자는 어디에 있습니까?스트림 레벨에 대한 if/remit 문을 작성합니다(해당 항목에 대한 입문서가 필요한 경우).
또한 Angular에서 Firebase 통합을 쉽게 하기 위해 Angularfire2를 사용했습니다.
코드는 다음과 같습니다.
import { Component, OnInit } from '@angular/core';
import { Observable, merge, pipe } from 'rxjs';
import { map, switchMap, filter, take } from 'rxjs/operators';
import { AngularFirestore, QuerySnapshot } from '@angular/fire/firestore';
@Component({
selector: 'pp-random',
templateUrl: './random.component.html',
styleUrls: ['./random.component.scss']
})
export class RandomComponent implements OnInit {
constructor(
public afs: AngularFirestore,
) { }
ngOnInit() {
}
public buttonClicked(): void {
this.getRandom().pipe(take(1)).subscribe();
}
public getRandom(): Observable<any[]> {
const randomNumber = this.getRandomNumber();
const request$ = this.afs.collection('your-collection', ref => ref.where('random', '>=', randomNumber).orderBy('random').limit(1)).get();
const retryRequest$ = this.afs.collection('your-collection', ref => ref.where('random', '<=', randomNumber).orderBy('random', 'desc').limit(1)).get();
const docMap = pipe(
map((docs: QuerySnapshot<any>) => {
return docs.docs.map(e => {
return {
id: e.id,
...e.data()
} as any;
});
})
);
const random$ = request$.pipe(docMap).pipe(filter(x => x !== undefined && x[0] !== undefined));
const retry$ = request$.pipe(docMap).pipe(
filter(x => x === undefined || x[0] === undefined),
switchMap(() => retryRequest$),
docMap
);
return merge(random$, retry$);
}
public getRandomNumber(): number {
const min = Math.ceil(Number.MIN_VALUE);
const max = Math.ceil(Number.MAX_VALUE);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
}
다른 해결책들이 더 낫지만 제가 이해하기 어려울 것 같아서 다른 방법을 생각해냈습니다.
1,2,3,4,5,6,7,8,9와 같은 ID로 증분 번호 사용, 문서 삭제 주의, 그렇지 않으면 누락된 ID가 있습니다.
컬렉션에 있는 문서의 총 수를 가져옵니다. 이와 유사한 것입니다. 이보다 더 나은 솔루션은 모르겠습니다.
let totalDoc = db.collection("stat").get().then(snap=>snap.size)이제 이것들이 나왔으니, 숫자의 무작위 목록을 저장할 빈 배열을 만들자, 우리가 20개의 무작위 문서를 원한다고 하자.
let randomID = [ ] while(randomID.length < 20) { const randNo = Math.floor(Math.random() * totalDoc) + 1; if(randomID.indexOf(randNo) === -1) randomID.push(randNo); }이제 우리는 20개의 무작위 문서 ID를 가지고 있습니다.
마지막으로 우리는 화재 저장소에서 데이터를 가져오고 무작위로 매핑하여 무작위 문서 배열에 저장합니다.ID 배열
const randomDocs = randomID.map(id => { db.collection("posts").doc(id).get() .then(doc => { if (doc.exists) return doc.data() }) .catch(error => { console.log("Error getting document:", error); }); })
저는 소방서에 처음입니다만, 이 답변을 통해 곧 소방서에서 더 나은 것이나 기본 제공 쿼리를 얻을 수 있을 것 같습니다.
친구와 격렬한 논쟁 끝에, 우리는 마침내 해결책을 찾았습니다.
문서 ID를 임의로 설정할 필요가 없는 경우ID, 문서의 이름을 컬렉션 크기로 지정하십시오.
예를 들어, 첫 번째 수집 문서의 이름은 '0'이고 두 번째 문서 이름은 '1'이어야 합니다.
그런 다음, 우리는 N과 같이 수집의 크기를 읽기만 하면, [0~N] 범위에서 임의의 숫자 A를 얻을 수 있습니다.
그런 다음 A라는 이름의 문서를 조회할 수 있습니다.
이렇게 하면 수집 중인 모든 문서에 동일한 무작위 확률을 제공할 수 있습니다.
의심할 여지 없이 승인된 답변은 매우 유용하지만 일부 문서 모음(약 100-1000개)이 있고 문서가 반복되지 않는다면 20-30개의 무작위 문서를 원합니다.(임의의 문제 앱 등의 경우).
위 솔루션의 문제:모음(예: 50)에 있는 소수의 문서의 경우 반복 확률이 높습니다.Fetched Docs Id 및 Add-in Query를 다음과 같이 저장하는 경우 이를 방지하려면:
queryRef = postsRef.whereField("random", isGreaterThanOrEqualTo: lowValue).where("__name__", isNotEqualTo:"PreviousId")
.order(by: "random")
.limit(to: 1)
여기서 PreviousId는 fetched된 모든 요소의 ID입니다. 이미 n개의 이전 ID 루프를 의미합니다.그러나 이 경우 네트워크 통화량이 높습니다.
내 솔루션:하나의 특수 문서를 유지하고 이 컬렉션의 ID 기록만 유지한 후 이 문서를 처음 가져온 다음 모든 임의 작업을 수행하고 앱 사이트에서 이전에 가져오지 않았는지 확인합니다.따라서 이 경우 네트워크 호출은 필요한 문서 수(n+1)와 동일합니다.
My 솔루션의 단점:문서를 유지해야 하므로 추가 및 삭제 시 쓰기.그러나 읽기가 매우 자주 발생하는 경우 대부분의 경우에 발생하는 쓰기가 좋습니다.
사용할 수 있습니다.listDocuments()문서 ID의 쿼리 목록만 가져오기 위한 속성입니다.그런 다음 다음 방법을 사용하여 임의 ID를 생성하고 다음을 사용하여 DocumentSnapshot을 가져옵니다.get()소유물.
var restaurantQueryReference = admin.firestore().collection("Restaurant"); //have +500 docs
var restaurantQueryList = await restaurantQueryReference.listDocuments(); //get all docs id;
for (var i = restaurantQueryList.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = restaurantQueryList[i];
restaurantQueryList[i] = restaurantQueryList[j];
restaurantQueryList[j] = temp;
}
var restaurantId = restaurantQueryList[Math.floor(Math.random()*restaurantQueryList.length)].id; //this is random documentId
rtdb와 달리 Firestore ID는 시간순으로 정렬되지 않습니다.따라서 Dan McGrath가 설명한 Auto-Id 버전을 사용하는 것은 Firestore 클라이언트에서 자동 생성된 id를 사용하는 경우 쉽게 구현할 수 있습니다.
new Promise<Timeline | undefined>(async (resolve, reject) => {
try {
let randomTimeline: Timeline | undefined;
let maxCounter = 5;
do {
const randomId = this.afs.createId(); // AngularFirestore
const direction = getRandomIntInclusive(1, 10) <= 5;
// The firestore id is saved with your model as an "id" property.
let list = await this.list(ref => ref
.where('id', direction ? '>=' : '<=', randomId)
.orderBy('id', direction ? 'asc' : 'desc')
.limit(10)
).pipe(take(1)).toPromise();
// app specific filtering
list = list.filter(x => notThisId !== x.id && x.mediaCounter > 5);
if (list.length) {
randomTimeline = list[getRandomIntInclusive(0, list.length - 1)];
}
} while (!randomTimeline && maxCounter-- >= 0);
resolve(randomTimeline);
} catch (err) {
reject(err);
}
})
파이어베이스 파이어스토어에서 목록 문서를 무작위로 얻는 방법이 하나 있는데, 정말 쉽습니다.제가 Firestore에 데이터를 업로드할 때, 저는 100만에서 100만까지의 임의의 값을 가진 필드 이름 "위치"를 만듭니다.Firestore에서 데이터를 가져오면 Order by 필드 "Position"을 설정하고 값을 업데이트합니다. 많은 사용자 로드 데이터와 데이터가 항상 업데이트되고 랜덤 값이 됩니다.
@Dan McGrath 기술을 기반으로 하는 Angular + Firestore를 사용하는 사람들을 위해, 여기 코드 스니펫이 있습니다.
아래 코드 조각은 1개의 문서를 반환합니다.
getDocumentRandomlyParent(): Observable<any> {
return this.getDocumentRandomlyChild()
.pipe(
expand((document: any) => document === null ? this.getDocumentRandomlyChild() : EMPTY),
);
}
getDocumentRandomlyChild(): Observable<any> {
const random = this.afs.createId();
return this.afs
.collection('my_collection', ref =>
ref
.where('random_identifier', '>', random)
.limit(1))
.valueChanges()
.pipe(
map((documentArray: any[]) => {
if (documentArray && documentArray.length) {
return documentArray[0];
} else {
return null;
}
}),
);
}
.rxjs는 임의 선택에서 문서를 확실히 가져올 수 있도록 재귀를 위한 rxjs 작업입니다.
재귀가 예상대로 작동하려면 두 개의 별도 기능이 필요합니다.
.expand() 연산자를 종료하려면 빈칸을 사용합니다.
import { Observable, EMPTY } from 'rxjs';
알겠습니다. 안드로이드용으로 하고 있지만 이 질문에 대한 답변을 올리겠습니다.내가 새로운 문서를 만들 때마다 난수를 시작하고 무작위 필드로 설정하기 때문에 내 문서는 다음과 같이 보입니다.
"field1" : "value1"
"field2" : "value2"
...
"random" : 13442 //this is the random number i generated upon creating document
임의 문서를 쿼리할 때 문서를 만들 때 사용한 것과 동일한 범위의 임의 번호를 생성합니다.
private val firestore: FirebaseFirestore = FirebaseFirestore.getInstance()
private var usersReference = firestore.collection("users")
val rnds = (0..20001).random()
usersReference.whereGreaterThanOrEqualTo("random",rnds).limit(1).get().addOnSuccessListener {
if (it.size() > 0) {
for (doc in it) {
Log.d("found", doc.toString())
}
} else {
usersReference.whereLessThan("random", rnds).limit(1).get().addOnSuccessListener {
for (doc in it) {
Log.d("found", doc.toString())
}
}
}
}
@ajzbc 답변을 기반으로 유니티 3D를 위해 이 글을 썼고 저를 위해 작동합니다.
FirebaseFirestore db;
void Start()
{
db = FirebaseFirestore.DefaultInstance;
}
public void GetRandomDocument()
{
Query query1 = db.Collection("Sports").WhereGreaterThanOrEqualTo(FieldPath.DocumentId, db.Collection("Sports").Document().Id).Limit(1);
Query query2 = db.Collection("Sports").WhereLessThan(FieldPath.DocumentId, db.Collection("Sports").Document().Id).Limit(1);
query1.GetSnapshotAsync().ContinueWithOnMainThread((querySnapshotTask1) =>
{
if(querySnapshotTask1.Result.Count > 0)
{
foreach (DocumentSnapshot documentSnapshot in querySnapshotTask1.Result.Documents)
{
Debug.Log("Random ID: "+documentSnapshot.Id);
}
} else
{
query2.GetSnapshotAsync().ContinueWithOnMainThread((querySnapshotTask2) =>
{
foreach (DocumentSnapshot documentSnapshot in querySnapshotTask2.Result.Documents)
{
Debug.Log("Random ID: " + documentSnapshot.Id);
}
});
}
});
}
자동을 사용하는 경우이것도 당신에게 도움이 될 수도 있습니다...
let collectionRef = admin.firestore().collection('your-collection');
const documentSnapshotArray = await collectionRef.get();
const records = documentSnapshotArray.docs;
const index = documentSnapshotArray.size;
let result = '';
console.log(`TOTAL SIZE=====${index}`);
var randomDocId = Math.floor(Math.random() * index);
const docRef = records[randomDocId].ref;
result = records[randomDocId].data();
console.log('----------- Random Result --------------------');
console.log(result);
console.log('----------- Random Result --------------------');
쉬움(2022년).다음과 같은 것이 필요합니다.
export const getAtRandom = async (me) => {
const collection = admin.firestore().collection('...').where(...);
const { count } = (await collection.count().get()).data();
const numberAtRandom = Math.floor(Math.random() * count);
const snap = await accountCollection.limit(1).offset(numberAtRandom).get()
if (accountSnap.empty) return null;
const doc = { id: snap.docs[0].id, ...snap.docs[0].data(), ref: snap.docs[0].ref };
return doc;
}
다음 코드(Flutter)는 Firebase 컬렉션에서 하나 또는 최대 30개의 임의 문서를 반환합니다.
- 모든 문서가 반복되지 않습니다.
- 최대 30개의 문서를 검색할 수 있습니다.
- 이 더 큰 약당이더큰것을 한다면.
numberOfDocuments컬렉션의 기존 문서보다 루프가 절대 종료되지 않습니다.
Future<Iterable<QueryDocumentSnapshot>> getRandomDocuments(int numberOfDocuments) async {
// Queried documents
final docs = <QueryDocumentSnapshot>[];
// Queried documents id's. We will use later to avoid querying same documents
final currentIds = <String>[];
do {
// Generate random id explained by @Dan McGrath's answer (autoId)
final randomId = FirebaseFirestore.instance.collection('random').doc().id;
var query = FirebaseFirestore.instance
.collection('myCollection') // Change this for you collection name
.where(FieldPath.documentId, isGreaterThanOrEqualTo: randomId)
.limit(1);
if (currentIds.isNotEmpty) {
// If previously we fetched a document we avoid fetching the same
query = query.where(FieldPath.documentId, whereNotIn: currentIds);
}
final querySnap = await query.get();
for (var element in querySnap.docs) {
currentIds.add(element.id);
docs.add(element);
}
} while (docs.length < numberOfDocuments); // <- Run until we have all documents we want
return docs;
}
언급URL : https://stackoverflow.com/questions/46798981/firestore-how-to-get-random-documents-in-a-collection
'programing' 카테고리의 다른 글
| *적용" 제품군이 정말로 벡터화되지 않았습니까? (0) | 2023.06.18 |
|---|---|
| 한 열의 최소값이 있고 다른 열의 값이 지정된 경우 레코드를 선택하려면 어떻게 해야 합니까? (0) | 2023.06.18 |
| 기존 Oracle 시퀀스를 사용하여 최대 절전 모드에서 ID를 생성하는 방법은 무엇입니까? (0) | 2023.06.13 |
| grid.arrange를 사용하여 가변 플롯 목록을 정렬하려면 어떻게 해야 합니까? (0) | 2023.06.13 |
| POI / Excel : "상대적" 방식으로 공식 적용 (0) | 2023.06.13 |