Reputation: 474
I want to build a view to show some events inside a listview in my app like this:
I have these two tables:
But I don't know how do a "inner join" between the tables USERS
and EVENTS
...
I tried this:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:project/Methods.dart';
import 'package:project/Views/CadastroUsuario.dart';
import 'dart:math';
class EventClass{
String owner;
String description;
String city;
String state;
String place;
}
class EventsListing extends StatefulWidget {
@override
EventsListingState createState() => new EventsListingState();
}
class EventsListingState extends State<EventsListing> {
List<EventClass> events;
@override
void initState() {
super.initState();
events = new List<EventClass>();
}
void buildEventClass(DocumentSnapshot doc) async {
EventClass oneEvent = new EventClass();
DocumentReference document = Firestore.instance.collection("users").document(doc["userid"]);
document.get().then((DocumentSnapshot snapshot){
oneEvent.owner = snapshot["name"].toString();
});
oneEvent.description = doc["description"];
oneEvent.place = doc["place"];
oneEvent.city = doc["city"];
oneEvent.state = doc["state"];
events.add(oneEvent);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Events'),
),
body: new StreamBuilder(
stream: Firestore.instance.collection("events").snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot){
if (snapshot.connectionState == ConnectionState.waiting)
return Text("Loading...");
return new ListView(
padding: EdgeInsets.only(left: 5.0, right: 5.0, top: 5.0),
children: snapshot.data.documents.map((document){
buildEventClass(document);
return events.length == 0 ? new Card() : item(events.last);
}).toList()
);
},
),
floatingActionButton: new FloatingActionButton(
tooltip: 'New',
child: new Icon(Icons.add),
onPressed: () async {
Navigation navigation = new Navigation();
navigation.navigaTo(context, CadastroUsuario());
},
),
);
}
Widget item(EventClass oneEvent) {
return new Card(
elevation: 4.0,
child: new Column(
children: <Widget>[
new Row(
children: <Widget>[
new Column(
children: <Widget>[
new Text(oneEvent.owner.toString(),
style: TextStyle(fontSize: 20.0),
overflow: TextOverflow.ellipsis,),
],
),
new Column(
children: <Widget>[
],
)
],
),
new Container(
color: Colors.blue,
height: 150.0,
),
new Row(
children: <Widget>[
new Row(
children: <Widget>[
new Text(oneEvent.description.toString(),
style: TextStyle(fontSize: 20.0),
overflow: TextOverflow.ellipsis,),
],
),
new Row(
children: <Widget>[
new Text(oneEvent.place.toString(),
style: TextStyle(color: Colors.grey[350]),
overflow: TextOverflow.ellipsis,),
],
),
new Row(
children: <Widget>[
new Text(oneEvent.city.toString() +' - '+ oneEvent.state.toString(),
style: TextStyle(color: Colors.grey[350]),
overflow: TextOverflow.ellipsis,),
],
)
]
)
],
)
);
}
}
But every time that I try to show these events I get this exception
Exception has occurred.
PlatformException(error, Invalid document reference. Document references must have an even number of segments, but users has 1, null)
What I'm doing wrong? How I can do a "inner join" between thesse tables and show the events?
I'm using the Firebase Firestore.
PS: I already know that Firestore is a noSQL database and have no "joins", but I want to do something like a join.
Upvotes: 7
Views: 30255
Reputation: 2668
As I was telling in the coments Firestore does not support multi collection querys cause its no relational DB. If you need to access multiple collections you would manage querys independently.
This is how I usually get related collections data (Sorry this is JS code but I dont know DART):
var data = {};
//First you get users data
DocumentReference document = Firestore.collection("users")
document.get().then((snapshot) => {
//In this case I will store data in some object, so I can add events as an array for a key in each user object
snapshot.forEach((userDoc) => {
var userDocData = userDoc.data()
if (data[userDoc.id] == undefined) {
data[userDoc.id] = userDocData
}
})
//So in this moment data object contains users, now fill users with events data
//In this var you count how many async events have been downloaded, with results or not.
var countEvents = 0
Object.keys(data).forEach((userDocId) => {
//Here Im creating another query to get all events for each user
SnapshotReference eventsForCurrentUserRef = Firestore.collection("events").where("userId", "==", userDocId)
eventsForCurrentUserRef.get.then((eventsForUserSnapshot) => {
//Count events
countEvents++
eventsForUserSnapshot.forEach((eventDoc) => {
var eventDocData = eventDoc.data()
//Check if array exists, if not create it
if (data[eventDocData.userId].events == undefined) {
data[eventDocData.userId].events = []
}
data[eventDocData.userId].events.push(eventDocData)
})
if(countEvents == Object.keys(data).length){
//Lookup for events in every user has finished
}
})
})
})
Upvotes: 11