Reputation: 2714
I hope somebody can assist me to the following implemenetation: I simply want to retrieve a random document from firestore.
Following this popular guide using the Auto-Id Version, I'm using auto generated document ids and Im saving them as field id
.
Firestore: How to get random documents in a collection
[..]Auto-Id version If you are using the randomly generated automatic ids provided in our client libraries, you can use this same system to randomly select a document. In this case, the randomly ordered index is the document id.[...]
It seems obvious to get a random id for the query, but for me as rookie im not sure where to get the auto id value randomly from what and how to fit in my _randomIndex
without running the query. How do I have to define my _randomIndex
now?
QuerySnapshot querySnapshot = await ref
.where('id', isGreaterThanOrEqualTo: _randomIndex)
.orderBy('id', descending: true)
.limit(1)
.get();
Thanks to all! I think maybe it isn't quite trivial for more people how to achieve the given approach by viewing the above guide and doing it with flutter.
Me for example hearing about uuids and random id's in flutter context, always refers me to the popular librarys such as https://pub.dev/packages/uuid/example and https://pub.dev/packages/flutter_guid/install
In my case they don't work, thanks to @Jigar Patel we can randomize it now perfectly. In the following example we can also determine the amount of documents:
import 'dart:math';
String getRandomGeneratedId() {
const int AUTO_ID_LENGTH = 20;
const String AUTO_ID_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const int maxRandom = AUTO_ID_ALPHABET.length;
final Random randomGen = Random();
String id = '';
for (int i = 0; i < AUTO_ID_LENGTH; i++) {
id = id + AUTO_ID_ALPHABET[randomGen.nextInt(maxRandom)];
}
Future<List<Model>> getData() async {
List<Model> dataList = [];
CollectionReference myRef = _db.collection('data');
final data = ['data','data']; // demo purposes only
// Retrieves 2 random data in a loop
for (int i = 0; i < 2; i++) {
// generate a random index based on the list length
// and use it to retrieve the element
String _randomIndex = getRandomGeneratedId();
QuerySnapshot querySnapshot = await myRef
.where('data', arrayContainsAny: data)
.where('id', isGreaterThanOrEqualTo: _randomIndex)
.orderBy('id', descending: false)
.limit(1)
.get();
dataList.addAll(_dataListFromSnapshot(querySnapshot));
}
return dataList;
}
Upvotes: 6
Views: 2423
Reputation: 5423
In case of Auto-Id version, you need to create a random id (for _randomIndex
) in the same way that firebase creates an id for a new document, like so.
import 'dart:math';
String getRandomGeneratedId() {
const int AUTO_ID_LENGTH = 20;
const String AUTO_ID_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const int maxRandom = AUTO_ID_ALPHABET.length;
final Random randomGen = Random();
final StringBuffer buffer = StringBuffer();
for (int i = 0; i < AUTO_ID_LENGTH; i++) {
buffer.write(AUTO_ID_ALPHABET[randomGen.nextInt(maxRandom)]);
}
return buffer.toString();
}
Upvotes: 4
Reputation: 2911
The post you linked mentions:
Later in our query section, the random value you generate is a new auto-id (iOS, Android, Web) and the field you query is the __ name __ field, and the 'low value' mentioned later is an empty string. This is by far the easiest method to generate the random index and works regardless of the language and platform.
For what I understand, you can generate a random value using the autoId()
method from Util.java. This is the same method that is used by Firestore to create a document Id. It will return a random String corresponding to a random Id. This Id does not match with any of your documents (except if you have no luck and that the method generate a random Id already assign to a document). Then, the comparison between Ids is done with the following code with random
set to the new generated Id:
queryRef = postsRef.whereField("random", isGreaterThanOrEqualTo: random)
.order(by: "random")
.limit(to: 1)
Upvotes: 1
Reputation: 622
I don't Know if that's the best solution , what really crossed my mind is something less complex like this:
1: Get all the document of specific collection from firestore .
2: get them all into a list .
3: shuffle the whole list and get the first index .
i think it will be something like this :
import 'dart:math'
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
List allDoc = [];
class AllDocs{
String collection = "collectionName";
FirebaseFirestore _firestore = FirebaseFirestore.instance;
Future<List> getAllDocs()async{
_firestore.collection(collection).get().then((result) {
for(DocumentSnapshot docss in result.docs ){
allDoc.add(Model.fromSnapshot(docss));
}
return allDoc;
});
}
final _random = Random();
var element = allDoc[_random.nextInt(list.length)];
print (element);
}
Upvotes: 1