1

I have a users collection with uId, name, photo

I have a visits collection with uId, userId, location

I have a recyclerview in which I want to show the location with the user name and photo

Can I use the reference field type? If so, how will Firestore know to link visits.userId == users.uId ?

Maybe I first need to query all the visits and then query the relevant user but 2 things:

  1. It means querying a lot of times.

  2. I didn't understand how to collect the joined collection into the adapter, which is based on one query?

Please advice Thanks

current code

visitsList = db.collection("visitsList");
Query query = visitsList.whereEqualTo("userId",prefs.getString("id","")).orderBy("visitDate", Query.Direction.ASCENDING);
FirestoreRecyclerOptions<AVisit> options = new FirestoreRecyclerOptions.Builder<AVisit>().setQuery(query, AVisit.class).build();
adapter = new VisitsListAdapter(options, VisitsListActivity.this);
RecyclerView rv = findViewById(R.id.rvVisitsList);
rv.setHasFixedSize(true);
rv.setLayoutManager(new LinearLayoutManager(this));
rv.setAdapter(adapter);

The code is a simple query from the collection, not sure how to get the name and photo from the userId field in that collection.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Amos
  • 1,321
  • 2
  • 23
  • 44
  • For #2) if you're having trouble making your code work, share the [minimal code that reproduces the problem](http://stackoverflow.com/help/mcve) (read the link please, as it's incredibly useful). – Frank van Puffelen Feb 23 '19 at 15:36
  • Updated. The current code a simple query from the collection. – Amos Feb 23 '19 at 15:41
  • Ah, so you're using FirebaseUI and are wondering how to show data from the user profile in a list of visits. For future questions: that would be a great title. :) I don't have any code ready for this, but I'd expect two main options: 1) load the additional user document in `populateView` or with a custom `parseSnapshot` implementation, 2) duplicate the relevant user data in the visits collection (which is quite normal in NoSQL databases). Also see Alex' answer here: https://stackoverflow.com/q/48756129. – Frank van Puffelen Feb 23 '19 at 16:03

1 Answers1

2

Can I use the reference field type?

Yes, you can use a reference field.

If so, how will Firestore know to link visits.userId == users.uId ?

Firestore results always comes from a single collection (at the moment). It does not automatically join the document from the users collection when you're reading from the visits collection. You will have to do this yourself.

That indeed means you'll be executing multiple reads, but it's often not nearly as slow as you may think. See Google Firestore - how to get document by multiple ids in one round trip?


Update: To show data from the user profile in a list of visits, there are two main options:

  1. load the additional user document in populateView or with a custom parseSnapshot implementation.

  2. duplicate the relevant user data in the visits collection (which is quite normal in NoSQL databases). Also see Alex' answer here: indexed query with FirestoreRecyclerAdapter.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • So how the reference field is helping me here? I do a simple visitsList.whereEqualTo("userId",prefs.getString("id","")) and I get the info from visits collection. How can I "integrate" the name and photo from the users collection into the adapter? (see updated code). Also, the name is a short string, an image is much heavier, though here I can query one user at the time but the integration (into the adapter) question is still relevant. – Amos Feb 23 '19 at 15:45
  • See https://stackoverflow.com/questions/46568850/what-is-firestore-reference-data-type-good-for for a Firestore engineer's explanation of the reference field type. – Frank van Puffelen Feb 23 '19 at 15:57
  • Thanks for the link. Reference is pointing to a specific collection.document so his explanation is a bit confusing (the comments there also reflect this confusion). Anyway, obviously this is irrelevant to my question. Thanks – Amos Feb 23 '19 at 16:13
  • I will check the populateview option you suggested. Thinking about it, shouldn't I use the onBindViewHolder event where all the data is actually "linked" to the viewholder? – Amos Feb 23 '19 at 16:17
  • I actually wonder if `parseSnapshot` isn't a better option for you, but either could work. Definitely consider caching the user data you look up, if you're likely to need the same user document multiple times in a time frame where it is unlikely to be modified. – Frank van Puffelen Feb 23 '19 at 18:13
  • For now I'm trying to add this in addSnapshotListener.onEvent. This will avoid the GUI interruption (like in onBindViewHolder). Will update soon. – Amos Feb 23 '19 at 19:04
  • I'm confused, it looks like the only place I can do that is in onBindView where I have access to all the viewHolder properties. – Amos Feb 23 '19 at 21:00