Flutter list .add function null - android

Future<List<DocumentSnapshot>> finallist() async {
List<DocumentSnapshot> finallist;
Future createList(QuerySnapshot snapshot) async {
List<DocumentSnapshot> listoflocationforsingle = snapshot.documents;
for (DocumentSnapshot u in listoflocationforsingle) {
print('Added ' + u.data['country']);
finallist.add(u);
}
}
finallist.add(u) fails with add on null error.
Exception has occurred.
NoSuchMethodError (NoSuchMethodError: The method 'add' was called on null.
Receiver: null
Tried calling: add(Instance of 'DocumentSnapshot'))
Even tho when I hover over the data in createlist(data), it shows list of QuerySnapshot with the data in my firestore database.

There is no single query that can get data from multiple subcollections. Firestore queries are shallow, and only work with documents within a single collection at a time. If you want data from three subcollections, you will need to be three queries, one for each subcollection.

Oh, my future function actually does it. Just that I needed to add in
List<DocumentSnapshot> finallist = []; // add in the ' = [] '

Related

Trying to access map field from a particular document in Flutter Firestore mobile application

I have a collection called Orders. This collection stores various orders. Each document has a field stockQuantity. Every day when new stock is added, it is added to this field (which is a map) alongside the date. Now I want to be able to list all the last values of the stock added for each order i.e. the stock added on the latest date. This is me trying to achieve this. I am getting an error error: The operator '[]' isn't defined for the type 'Object'. (line 40).
Also I am not sure if this will work.
class StockService {
static Future<List<in
t>> getLatestStockQuantity() async {
List<int> latestStockedQuantityList = [];
QuerySnapshot snapshot = await FirebaseFirestore.instance.collection(
'orders').get();
for (var doc in snapshot.docs) {
Map<String, dynamic> stockedQuantityMap = doc.data()!['stockQuantity'];
if (stockedQuantityMap != null) {
int latestStockedQuantity = stockedQuantityMap.values
.last['stockedThisDay'];
latestStockedQuantityList.add(latestStockedQuantity);
}
}
return latestStockedQuantityList;
}
}
on another page I am using a ListView.builder to display the data
I have tried troubleshooting by looking at other posts on stack, etc. still no luck.

Firestore conditional array query

I am trying to get all documents where the length of the "users" array is less than 2 and where the userId is not present already. I am doing the following query, but it is not executing correctly. What is the problem and how can I fix it? I just want all documents where there is only one entry in the array "users" and where the array does NOT contain the current userId.
await FirebaseFirestore.instance
.collection('rooms')
.where("users"[0], isNotEqualTo: userId)
.where('users'[1], isEqualTo: null)
.get()
.then((snapshot) async {
// If no empty room is found, create room
if (snapshot.docs.isEmpty) {
print("No empty room found, creating new room");
roomId = await createRoom(userId);
return roomId;
}
You can't query individual array elements in Firestore. You can only check whether an array contains a specific item.
It sounds like your array items have a specific meaning, in which case you should create (nested) fields that indicate/name the roles. For example:
participants: {
creator: "uid1",
receiver: "uid2"
}
With that you can then query the nested fields with dot notation:
.where("participants.creator", "!=", "uid1")
.where("participants.receiver", "==", null)
Keep in mind there that the participants.receiver field still has to exist in the latter case and have a value of null. Firestore can't filter in fields that don't exist.

Flutter : check if there's specific data in the subcollection

I'm creating a post that uploads data to Firestore's sub-collection and brings it up to MyBookmark page. It's good to create a sub-collection and upload data simply. And now I'd like to add a 'data duplication prevention' function here.
If the post is already saved in the bookmark, should not upload it.
For this purpose, I would like to check if the post is already in the collection when I press the bookmark button.
IconButton(
onPressed: () async {
//get userModel
UserModelState _userModelstate =
Provider.of<UserModelState>(context, listen: false);
//=========================================
//duplication data test
DocumentReference bookmarkRef = Firestore.instance
.collection(COLLECTION_USERS)
.document(_userModelstate.userModel.userKey)
.collection(COLLECTION_BOOKMARk)
// .where(KEY_BOOKMARK_PRODUCTKEY, isEqualTo: productKey)
.document();
DocumentSnapshot bookmarkSnapshot = await bookmarkRef.get();
//test (return "No exist")
if(bookmarkSnapshot.exists) {
print("Yes exist");
} else {
print("No exist");
}
I tried writing a code to check if there was data in the collection, but it is always printed as "No exist".
How can I confirm the existence of a specific document in collection?
Thank you.
If the productKey is supposed to be unique in the Bookmark collection of the user, consider using the productKey as the document ID. Since document IDs are by definition unique within their collection, using them guarantees unique product keys without you having to write any code for it.
That said, you current code can't work because you call document(). Whenever you call document() without any parameters, it generates a reference to a new unique document. And since you immediately call get() on that reference, the document will (also: by definition) not exist yet.
To check if a document with a specific product ID exist, you will need to run a query:
CollectionReference bookmarksRef = Firestore.instance
.collection(COLLECTION_USERS)
.document(_userModelstate.userModel.userKey)
.collection(COLLECTION_BOOKMARk);
Query bookmarkQuery = bookmarksRef.where(KEY_BOOKMARK_PRODUCTKEY, isEqualTo: productKey);
QuerySnapshot bookmarkSnapshot = await bookmarkQuery.get();
if (bookmarkSnapshot.size > 0) {
print("product key already in use");
}

How to add items to a StreamController in flutter

I want to return a list of members via a StreamController.
batches collection contains batch details and ids of members assigned to the batch.
So, in-order to get the list of members in a batch, have to loop through batch collection and get the ids of members, then match with members collection and return the matching member data as stream.
final CollectionReference _batchCollectionReference =
Firestore.instance.collection('batches');
final CollectionReference _membersCollectionReference =
Firestore.instance.collection('members');
final StreamController<List<Member>> _membersController =
StreamController<List<Member>>.broadcast();
Stream getMembers(String batchId) { //passing a batch id
_batchCollectionReference
.document(batchId)
.snapshots()
.map((batchSnapshot) => Batch.fromData( //return as Batch type
data: batchSnapshot.data, batchId: batchSnapshot.documentID))
.listen((snapshot) {
List<String> members = snapshot.members; //list of members
members.forEach((member) {
var data = _membersCollectionReference
.document(member)
.snapshots()
.map((memberData) => Member.fromData(data: memberData.data)); //return as Member type
_membersController.add(data);
});
});
return _membersController.stream;
}
}
The problem is I couldn't able to push the member data to the StreamContoller.
It says,
The argument type 'Stream<Member>' can't be assigned to the parameter type 'List<Member>'
The stream should contains instance of members; Ex: [[instance of 'Member'], [instance of 'Member'], [instance of 'Member']]
If I got the data like this way, it would be easy to loop and do the other stuff.
I couldn't able fix this issue. Any help would be appreciated.
Firstable when you need to add a list to the stream so convert your map data to a list, just adding toList() at the end of you map as follows:
members.forEach((member) {
var data = _membersCollectionReference
.document(member)
.snapshots()
.map((memberData) => Member.fromData(data: memberData.data)).toList();
And to push the data in the Stream, you need to use sink.add() this can be an example of a function to push data into the stream and the other one to get the values:
final StreamController<List<Member>> _membersController = StreamController<List<Member>>.broadcast();
/// Inputs
Function(List<Member>) get changeMembers => _membersController.sink.add;
/// Getters
String get members => _membersController.value;
In your case you can do it directly in this way:
_membersController.sink.add(data);
Hope it helps, for more info please check this video or the documentation about streams in dart.

Firebase Cloud Firestore Query whereEqualTo for reference

I am trying to create a query which only selects documents whose reference is equal to a given reference, using Java for Android development. A document which it would match contains the reference for the path "/users/someUser". I am creating the reference like so:
DocumentReference ref = mDatabase.document("users/someUser");
I have also tried:
DocumentReference ref = mDatabase.document("/users/someUser");
Then the query:
Query query = mDatabase.collection("myCollection").whereEqualTo("refField", ref).limit(10);
However, when I run the query and check the task.isSuccessful() in the onComplete method, it's not passing, i.e. it didn't work, whereas when I remove the .whereEqualTo(), it passes and the task's result isn't empty. How can I properly use .whereEqualTo() to check for all documents containing a specific reference?
An example of a document that should match my query would be:
/myCollection/GDpojS5koac2C7YlIqxS which contains the field:
refField: /users/someUser (value of type reference)
And an example of a document that should not match my query would be:
/myCollection/J5ZcVAMYU1nI5XZmh6Bv which contains the field:
refField: /users/wrongUser (value of type reference)
I think you need to add a get() method to run the query and add an onCompletionListener.
Something like this should work:
mDatabase.collection("myCollection")
.whereEqualTo("refField", ref)
.limit(10)
.get()
.addOnCompleteListener({task ->
if(task.isSuccessful){
val result = task.result
})
The above example is in kotlin, but i guess in java it is something similar
You need not to worry about the documents, if you create a query based on your fields then all the documents will be returned in the "QuerySnapshot" object,
for eg,
CollectionReference collectionReference = db.collection(FIRESTORE_USERS);
DocumentReference documentReference = collectionReference.document(userID);
CollectionReference notificationCollection = documentReference.collection(FIRESTORE_NOTIFICATIONS);
notificationCollection.whereEqualTo(USER_TYPE, userType)
.whereGreaterThanOrEqualTo(SEND_AT, calendar.getTime())
.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot documentSnapshots) {
List<DocumentSnapshot> snapshotsList = documentSnapshots.getDocuments();
ArrayList<NotificationCollections> notificationCollectionsArrayList = new ArrayList<>();
for (DocumentSnapshot snapshot : snapshotsList) {
// each document having that particular field based on query
}
}});
in the above example I am fetching all those documents which match a particular user id and also having time greater than or equal to supplied time (time will not be used in your case)
I hope this helps...
Happy coding :)

Categories

Resources