How to search list of queries and combine them to a single query? - firebase

I am working on a social networking app whose data model is as follows:
Here posts collection contains multiple documents with same or different tag fields, a user can follow multiple tags I already have those tags in a list I need to extract the documents where tag is equal to an element of that list and sort them according to time stamp
getPosts() async {
for (int i = 0; i < Constants.hashtags.length; i++) {
QuerySnapshot dataDoc = await Firestore.instance
.collection("posts")
.where("tag", isEqualTo: Constants.hashtags[i])
.getDocuments();
}
}
Here Constants.hashtags is list of tags that a user if following. I am able to get all documents using above code but I don't know how to merge these documents in a single and sorted way which can be further presented to user in a List.builder form.

Looking at the documentation Here,
you can see the where has an optional parameter whereIn
Query where (
dynamic field,
{dynamic isEqualTo,
dynamic isLessThan,
dynamic isLessThanOrEqualTo,
dynamic isGreaterThan,
dynamic isGreaterThanOrEqualTo,
dynamic arrayContains,
List arrayContainsAny,
List whereIn,
bool isNull}
)
And you can use it Like
QuerySnapshot dataDoc = await Firestore.instance
.collection("posts")
.where("tag", whereIn: Constants.hashtags)
.getDocuments()
This query snapshot contains list of all documents that has a tag field which is equals to Constants.hashtags

Related

Retrieve field information form Firestore database

So I want to retrieve name of a user which is inside a field in firestore.
The whole sequence in given in image below.
I want to get the string value 'a' which is inside (chatroom->a_qaz->users->'a').
I am trying to get it with this code but its not working. How to get the field information.
getOtherUserByUsername() async {
return await FirebaseFirestore.instance
.collection("chatroom")
.doc("chatRoomId")
.get();
First of all, let's get the document from your collection.
collection.doc(), as per reference, gets the actual ID as parameter. In your case, you need to specify "a_qaz". After that, you get the document and then you can read the fields. Your code should look like this:
let chatRoom = await FirebaseFirestore.instance
.collection("chatroom")
.doc("a_qaz")
.get();
let users = chatRoom.get("users");
users will store, then, the list of users that's in that field.

Flutter Firebase Pagination - Nested Query

I am relatively new to the Flutter world and need some help in efficiently querying a nested Firebase query with pagination in Flutter.
I am building an app where I have a few thousand of user selected documents in collectionA (selected from >100k documents from collectionB) and need to loop through a chunk of 10 documents (whereIn limit of 10) queried via stream. My current implementation (snippet below) takes a list of document ID's "d" and chunks in a list of 10 via quiver/iterables. The drawback of the methodology is that it reads thousands of user documents upfront before displaying it in the app. I would like to use a pagination and control the reads.
Would you suggest a solution (with a code snippet) on how to use the pagination through thousands of user selected documents?
Future<List<Article>> fbWhereGT10Article(
String collection, String field, List<dynamic> d) async {
final chunks = partition(d, 10);
// print(chunks);
final querySnapshots = await Future.wait(chunks.map(
(chunk) {
Query itemsQuery = FirebaseFirestore.instance
.collection(collection)
.where(field, whereIn: chunk);
// .orderBy('timestamp', descending: true);
return itemsQuery.get();
},
).toList());
return querySnapshots == null
? []
: await Stream.fromIterable(querySnapshots)
.flatMap((qs) =>
Stream.fromIterable(qs.docs).map((e) => Article.fromFirestore(e)))
.toList();
}

Get data from subcollection in firestore flutter

In the 1st screen shot there are many documents in collection users. Each documents contains further collection jobPost and that collection contains further documents and its meta data.
What I want here is go to the every document of collection users and further subcollection jobPost and fetch all the documents.
Suppose first it should go to document 1 in collection users, in the document 1 it should fetch all the documnets in subcollection jobPost then it should go to the 2nd document of collection users and then get all the documents in the subcollection jobPost and so on. what will be the query or implementation to this technique
What you're describing is known as a collection group query, which allows you to query all collections with a specific name. Unlike what the name suggests, you can actually read all documents from all subcollections named jobPost that way with:
FirebaseFirestore.instance.collectionGroup('jobPost').get()...
When performing a query, Firestore returns either a QuerySnapshot or a DocumentSnapshot.
A QuerySnapshot is returned from a collection query and allows you to inspect the collection.
To access the documents within a QuerySnapshot, call the docs property, which returns a List containing DocumentSnapshot classes.
But subcollection data are not included in document snapshots because Firestore queries are shallow. You have to make a new query using the subcollection name to get subcollection data.
FirebaseFirestore.instance
.collection('users')
.get()
.then((QuerySnapshot querySnapshot) {
querySnapshot.docs.forEach((doc) {
FirebaseFirestore.instance
.document(doc.id)
.collection("jobPost")
.get()
.then(...);
});
});
**
if you not have field in first collection document then its shows italic thats means its delte by default otherwise if you have field in first collection document then you can access it easily so this is the best way that i share
**
static Future<List<PostSrc>> getAllFeedPosts()async
{
List<PostSrc> allPosts = [];
var query= await FirebaseFirestore.instance.collection("posts").get();
for(var userdoc in query.docs)
{
QuerySnapshot feed = await FirebaseFirestore.instance.collection("posts")
.doc(userdoc.id).collection("userPosts").get();
for (var postDoc in feed.docs ) {
PostSrc post = PostSrc.fromDoc(postDoc);
allPosts.add(post);
}
}
return allPosts;
}

How to filter Firebase Documents that are in a list of DocumentReferences?

I'm currently building a social network app using Firebase and Flutter, and I've stumbled onto a bit of a problem. My homepage has two tabs, one that contains all posts on the app in chronological order, and the other that contains the posts of the people you follow. The DocReferences of the people the user follows is inside a list. Currently, the code looks like this:
if (myFollows.isNotEmpty)
for (int j = 0; j < myFollows.length; j++) {
await FirebaseFirestore.instance
.collection('posts')
.orderBy('date', descending: true)
.where('user', isEqualTo: myFollows[j])
.get()
.then((value) {
//code
});
But, as you can see, I create seperate queries for each of the followed users, so the resulted list of posts isn't in chronological order.
So, my question is, if there is a way I could query the post documents where the user variable is contained inside the list myFollows, instead of comparing it to each of its values one by one?
Remove the loop and use whereIn. This should work
if (myFollows.isNotEmpty)
await FirebaseFirestore.instance
.collection('posts')
.orderBy('date', descending: true)
.where('user', whereIn: myFollows) //this line changed
.get()
.then((value) {
//code
);
In your 1st execution, you may need to add a new index... just follow the web link (in error message) that will help create this required index.
May not work if following more than 10 users as this is a built-in limit in Firestore (maximum 10 comparisons).
In that case, there is no built-in solution... you need to keep your loop and append every single query separately... then sort your final list.

Put only existing subcollection in a list firebase(flutter)

I've been trying to put document snapshots of a sub-collection in a list. The code for it is something like this:-
getcoffeebuyerlist() async {
DocumentSnapshot coffeebuyers;
List<DocumentSnapshot> finalCoffeBuyerList = [];
for (var i = 0; i < profiles.length; i++) {
coffeebuyers = await Firestore.instance
.collection('profileData')
.document(profiles[i].uid)
.collection('coffeeprices')
.document(profiles[i].uid)
.get();
finalCoffeBuyerList.add(coffeebuyers);
}
return finalCoffeBuyerList;
}
There are two profile and only one of which has a sub-collection 'coffeeprices'.
My doubt here is by trying get snapshot of sub-collections, will I automatically be creating an empty document for the second profile for which sub-collection doesn't exist and put in finalCoffeBuyerList list?
Or only those(one in my case) sub-collection which already exist are added to this list?
Your code here will never create any documents. get() doesn't create a document if the document doesn't already exist. You should check the returned DocumentSnapshot to see if the document actually exists. Something like this:
if (coffeebuyers.exists) {
finalCoffeBuyerList.add(coffeebuyers);
}
The only way to create a document is with add() or set().

Resources