0
votes

i have a search bar that receives a query string from the user, if the query string is empty, like i just initiated the search operation, it fetches all documents in posts collection...if user starts typing inside the search bar...it takes the typed text and compare it to a field inside each document in firestore collection and if it matches...its retrieves matched documents and it and previews them in screen, if the user deleted his typed query string...so the query string is empty again...so it fetches all documents again...i use provider package to conduct the query string to database fetch function like so:

Provider:

import 'package:flutter/foundation.dart';

class QueryStringProvider extends ChangeNotifier {
  String _queryString = '';

  String getQueryString() => _queryString;

  updateQueryString(String userQueryString) {
    _queryString = userQueryString;
    notifyListeners();
  }
}


the database function:

Stream<QuerySnapshot> filterAllPosts(String query) {
    return query.isEmpty
        ? _postsCollection.snapshots()
        : _postsCollection
            .where('postSubtitles', arrayContains: query)
            .snapshots();
  }

the following is a stream builder wrapped inside a Consumer<QueryStringProvider>, the Streambuilder receives all data retrieved from database fetch function, and populate the data according to my preferred layout structure:

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Consumer<QueryStringProvider>(
        builder: (context, data, _) {
          return StreamBuilder<QuerySnapshot>(
            // stream: DatabaseService().listenToAllGigs(),
            stream: DatabaseService().filterAllGigs(data.getQueryString()),
            builder: (context, snapshot) {
              return !snapshot.hasData
                  ? Center(child: Text(''))
                  : snapshot.data.documents.length > 0
                      ? ListView.builder(
                          itemCount: snapshot.data.documents.length,
                          itemBuilder: (context, index) {
                            DocumentSnapshot data =
                                snapshot.data.documents[index];
                            Map getDocData = data.data;

                            return GestureDetector(
                              child: PostItem(
                                appointed: getDocData['appointed'],
                                appointedUserFullName:
                                    getDocData['appointedUserFullName'],
                                postId: getDocData['gigId'],
                                postTitle: getDocData['postTitle'],
                                postSubtitles: getDocData['postSubtitles'],
                                postBody: getDocData['postBody'],
                                // onDeleteItem: () => model.deleteGig(index),
                              ),
                            );
                          })
                      : Center(
                          child: Text(
                          'No Posts matching your criteria',
                          style: TextStyle(fontSize: 16),
                        ));
            },
          );
        },
      ),
    );
  }


i have three questions about how to reduce cloud reads with the above code:

1) is there any problems that i fetch all documents when i initiate the search operation and the query string is empty?

2)when users starts typing inside the search bar...does this mean that all the fetched data get lost..and we are making new reads again with filtering?...or it just filters what i've already fetched from initiating the search operation from the start?

3) when user deletes the query string and cancels filtering and and query string is now empty...does this mean that i will make a new full read to the cloud collection again...so everytime the users types or deletes the query string i iterate through all the collection again?*

Execuse me if the question is too long...but it is much closer to theoretical concepts rather than code...

any clarifications would be much appreciated...

many thanks.

1
You should try mixing data between Firebase Realtime Database and Cloud Firestore. - Rehmat Singh Gill
yes why not....but what would be the main benefit of this mix?!....each post will contain data which i store in cloud firestore collection "posts"...and multimedia files which i store them in firebase storage by post id...so every post fetches its multimedia files along the way....whats would be the main benefit of using Firebase Realtime Database here? - mohamed mostapha
The benefit of mixing will be that Firebase Realtime Database does not calculate price on number of times data was Read, Written or Deleted. So, by shifting some of your data to RTDB, your several read, writes will be saved. - Rehmat Singh Gill
i see...didn't know that RTBD calculates this way....i will check the RTDB thoroughly and compare how the bill will get affected by this shift.....thanks again for pointing me to this direction :) - mohamed mostapha

1 Answers

0
votes

What I suggest is querying the result only if the user has entered some specific number of characters and all of them are valid. Like, in my case, I ensure that the user has entered at least 3 characters and all of them are alphabets or numbers.