StreamBuilder(
stream: _firestore
.collection('MessageData')
.where( 'RecieverId', isEqualTo: RecieverId)
.where('SenderId', isEqualTo: _auth.currentUser!.uid)
//I Want OR operator here logicaly. How can i do this?
.where( 'RecieverId', isEqualTo: _auth.currentUser!.uid)
.where('SenderId', isEqualTo: RecieverId)
.snapshots(),
builder: (context, snapshot) {
return ListView(
children: snapshot.data!.docs.map((e) {
return Text(e['Message']);
}).toList(),
);
},
)
Please go this link to see firestore image.
Use in operator. This allow to check up to 10 equalities according to documentation.
See https://firebase.google.com/docs/firestore/query-data/queries#in_and_array-contains-any
Related
I have a Streambuilder that takes Firebase Firestore snapshot as a Stream and I would like to add initalData to the Streambuilder.
How can I pass initalData to the Streambuilder?
The Code:
StreamBuilder(
stream: FirebaseFirestore.instance
.collection("events")
.snapshots(),
builder: (BuildContext ctx, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData || snapshot.data.docs.isEmpty) {
return NoDataRelatedLocation();
}
if (snapshot.hasError) {
return Text(snapshot.error.toString());
} else {
return new RelatedLocationListing(
relatedLocationList: snapshot.data.docs,
);
}
},
),
You can add initialData to StreamBuilder:
StreamBuilder(
initialData: ..... // <~~~ add it here.
stream: ...
builder: ...
You just need to make sure that your initialData matches that type of data coming from the stream. Since QuerySnapshot is a Firebase specific type, you should map your stream to a data type that you can create and that's known to you.
Here's a pseudo code:
initialData: [MyDataType()],
stream: FirebaseFirestore.instance
.collection("events")
.snapshots().map((snapshot) => MyDataType.fromMap(snapshot.doc));
I am querying a firestore collection in Flutter using where and arrayContains, for some reason it is not working as expected for me.
StreamBuilder(
stream: (_searchTerm.length >= 3)
? FirebaseFirestore.instance.collection("users").snapshots()
: FirebaseFirestore.instance
.collection('users')
.where('email', arrayContains: _searchTerm)
.snapshots(),
builder: (ctx, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
}
final results = snapshot.data.docs;
print(results.length);
return ListView.builder(
shrinkWrap: true,
itemCount: results.length,
itemBuilder: (ctx, index) => Text(
results[index].data()['display-name'],
),
);
})
The _searchTerm variable is populated as I type in some values into the textfield and when it hits a length of three characters that's when the above query fires.
For example when I type in test the query should only return the values that contain test in it, but I am getting the whole collection with and without the value test.
Please advice!
EDIT - Posting a screenshot of my firestore data structure
When you do the following:
FirebaseFirestore.instance
.collection('users')
.where('email', arrayContains: _searchTerm)
.snapshots(),
You are looking for documents inside the users collection that have _searchTerm as an item of the email array, property of a user document.
There are two problems:
I don't think the email property of your users is an array.
Firebase does not perform substring searches
I think you will need to use a third-party application for searches on Firestore. A popular one is Algolia that comes with a quite powerful FREE plan.
I am trying to display a realtime chat-screen in flutter with with firebase-firestore (equal to the homescreen of whatsapp).
Working: Creating a list of all the contacts "peers". Have a Look at my Listview:
Container(
child: StreamBuilder(
stream:
//FirebaseFirestore.instance.collection('users').snapshots(),
FirebaseFirestore.instance
.collection('users')
.doc(currentUserId)
.collection('peers')
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(themeColor),
),
);
} else {
return ListView.builder(
padding: EdgeInsets.all(10.0),
itemBuilder: (context, index) =>
buildItem(context, snapshot.data.documents[index]),
itemCount: snapshot.data.documents.length,
);
}
},
),
),
not working: Loading specific data for each tile like last message or name. I cant query this at the time of creating my first list (first query returns peer-ids, second returns userdata of a peer-id). My buildItem method consists of another streambuilder, however, as soon as the first streambuilder makes changes, the app freezes.
Widget buildItem(BuildContext context, DocumentSnapshot document) {
return StreamBuilder<DocumentSnapshot>(
stream: FirebaseFirestore.instance
.collection('users')
.doc(document.data()['peerId'])
.snapshots(),
builder: ...
Is this the proper way to nest streams? Simple Listviews are documented quite well, but i couldn't find a good example on this on google. Any help is appreciated.
Try creating your stream just once in initState and pass it onto this method:
//in initState
peersStream = FirebaseFirestore.instance
.collection('users')
.doc(currentUserId)
.collection('peers')
.snapshots(),
Then use stream: peersStream in the StreamBuilder.
Also, it is recommended to use widget-classes over methods for widgets: https://stackoverflow.com/a/53234826/5066615
I want to find all the documents in the 'communities' collection, where the user's id is contained in the 'members' array.
But my firebase query is just returning ALL the documents in the 'communities' collection instead of just the ones I queried.
Stream<QuerySnapshot> get userCommunities {
return communityCollection.where('members', arrayContains: uid).orderBy('lastActive', descending: true).snapshots();
}
...
StreamBuilder(
stream: DBService().userCommunities,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasData)
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
return ListTile(title: Text(snapshot.data.documents[index]['name']));
});
else
return Container();
},
),
testCommunity2 does not contain the user's id in members but my app displays both communities in the listview
Fixed it! I found that my uid was returning null in return communityCollection.where('members', arrayContains: uid)
I am trying to calculate the number of unread messages. In the first streambuilder I need to get all the document id's which match the first query.
Within that document ID I can then access the subcollection within that document and perform another query. I then need to access the result of that query.
However, within the attempt below the console outputs "past first stream" but does not enter the second streambuilder.
return StreamBuilder(
stream: Firestore.instance
.collection('conversations')
.where('user_id', isEqualTo: Provider.of<User>(context).id)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData)
return Center(child: CircularProgressIndicator());
else {
print('past first stream');
StreamBuilder(
stream: Firestore.instance
.collection('conversations')
.document('#32#0#')
.collection('messages')
.where('customer_message_read', isEqualTo: false)
.snapshots(),
builder: (context, snapshot) {
print('im through second stream');
if (!snapshot.hasData)
return Center(child: CircularProgressIndicator());
print('nope');
QuerySnapshot querySnap = snapshot.data;
print(querySnap.documents.length);
return Center(child: CircularProgressIndicator());
},
);
return Scaffold(
backgroundColor: Colors.black,
body: _children[_selectedPage],
bottomNavigationBar: _bottomNavigationBar(context),
resizeToAvoidBottomPadding: true,
);
}
},
);
You've created second StreamBuilder but did not return it