i have a problem with a Flutter application. I want to receive data from a firebase firestore by an Document id. The problem is, i cant replicate the data in one collection, so i have to use two collections.
My data ist a Measurement(String, String,..., List) MeasurementData(String,String,Number)
As far as i understand the Firestore i cant make such a list in one collection, so i have created a second one in whitch each document consists of three arrays. I also save the id from the Measurement Document where it belongs to. To use it in Flutter a use a StreamBuilder widget. For easer access i convert the document bevor using into a Dart Object. Because i have two Streams which should be converted to one Object i have a predessecor StreamMeasurement object which is basicly the same as the Measurement Object, but without the MeasurementData list, because this first needs to be created, instead it only saves a id for the measurementData Document. After that i use the Rx.zip2 to create an Measurement Object from the StreamMeasurement Object and add the List to have a complete object.
Class Service
/// The firebase instance
FirebaseFirestore db = FirebaseFirestore.instance;
///Finds and returns a [Measurement] by its [id]
Stream<Measurement> getById(String id) {
Stream<StreamMeasurement> streamMeasurementStream =db.collection("measurements").doc(id)
.snapshots().map((document) => StreamMeasurement.fromJson(document.data()!));
return Rx.zip2(streamMeasurementStream, getMeasurementDataStreamById(id)
, (StreamMeasurement streamMeasurement, List<MeasurementData> measurementData) {
Measurement measurement = Measurement.fromStreamMeasurement(streamMeasurement, measurementData);
if(measurement == null)
{
//TODO Write a concrete exception to throw and catch
throw Exception('Measurement Stream is null');
}
return measurement;
}) ;
}
/// Returns a [Stream<List<MeasurementData>>] for a given Measurement id
Stream<List<MeasurementData>> getMeasurementDataStreamById(String id)
{
return db.collection("measurementData").where("measurement", isEqualTo: id).
snapshots().
map((querySnapshot) => querySnapshot.docChanges)
.expand((changes) => changes)
.map((change) => change.doc).map((document) => MeasurementData.fromJson(document.data()!));
}
Class DetailScreen
@override
Widget build(BuildContext context) {
MeasurementService measurementService = MeasurementService();
Stream<Measurement> measurementstream = measurementService.getById(
"GmfzveKeozkcfdlrk75s");
return StreamBuilder<Measurement>(
stream: measurementstream,
builder: (BuildContext context, AsyncSnapshot<Measurement> snapshot) {
if (snapshot.hasError) {
print(snapshot.error);
return Text('Something went wrong' + snapshot.error.toString());
}
if (snapshot.connectionState == ConnectionState.waiting) {
print(snapshot);
return Text("Loading" + snapshot.connectionState.toString());
}
Measurement? measurement = snapshot.data;
return SafeArea(
Print(snapshot) => I/flutter (19335): AsyncSnapshot(ConnectionState.waiting, null, null, null)
The result is, that the StreamBuilder is stuck in ConnectionState.waiting state if i use the getById(id) function
Okay, ... Question solved. The problem was a unmatched whitespace before the id EDIT: I had hardcodet the ID manually in the database, while writing i had left an whitespace before id, that doesnt belongs there and so the request doesnt work like " 1234" should be "1234"