0

I have a list of objects inserted in a Firestore Recycler and I need to sort them by the distance of the current user with the distance of the user from the object, I was able to calculate the distance between them by obtaining the current location of the user and pulling the location of the publisher of the object in question, it returns the distance in meters between them, and I wanted to use this as a parameter to order the data according to the value obtained, however, the only way to order the data obtained is using this document firestore queries Firestore

But it costs me dearly and is not very valid, is there anything I can do to change the order of the listed objects according to this local distance variable that I created?

Example

 if(locationResult != null && locationResult.getLocations().size() > 0){

    int latestLocationIndex = locationResult.getLocations().size() - 1;
    latitudeUser = locationResult.getLocations().get(latestLocationIndex).getLatitude();
    longitudeUser = locationResult.getLocations().get(latestLocationIndex).getLongitude();
    localizacaoUser.setLatitude(latitudeUser); // Latitude do usuário adquirida
    localizacaoUser.setLongitude(longitudeUser); 
    query.addSnapshotListener(new EventListener<QuerySnapshot>() {
        @Override
        public void onEvent(@Nullable QuerySnapshot documentSnapshots, @Nullable FirebaseFirestoreException e) {
            for (DocumentChange doc : documentSnapshots.getDocumentChanges()){
                if (doc.getType() == DocumentChange.Type.ADDED){

                    AnuncioPrincipal anuncioPrincipal1 = doc.getDocument().toObject(AnuncioPrincipal.class);
                    Location localAnuncioAtual = new Location("ProviderAun");

                    localAnuncioAtual.setLatitude(anuncioPrincipal1.getLatAnun());
                    localAnuncioAtual.setLongitude(anuncioPrincipal1.getLongAnun());
                    Log.i("valor2848", "onEvent: "+localizacaoUser.distanceTo(localAnuncioAtual)/1000+" Km Used by" +
                            anuncioPrincipal1.getCidadeAnunciante()); // CityUser - Actual City

                }
            }
        }
    });

Basically I want to add an extra field that will be used to sort the data listed in the Recycler, but that is not in the Firestore, because if it is in the Firestore, each user will be changing this variable per minute.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
luke cross
  • 321
  • 1
  • 2
  • 19
  • 1
    Executing a different query if you need a different sort order seems sensible to me at first glance. You're saying: "But it costs me dearly and is not very valid" Can you explain what you mean by that? – Frank van Puffelen Jun 25 '20 at 13:44
  • We pay per consultation, so if I do this consultation by state ... So this can cause many recordings, since each user is some distance from each object ... Imagine the situation of a thousand users for 10 objects .. . – luke cross Jun 25 '20 at 14:14
  • 1
    You might want to validate that assumption. If your documents don't change, they'll be read fro the local cache and you won't be charged for each read. If the documents *do* change, you actually should be re-reading them from the database server to ensure you have the latest data. In the latter case you may want to consider using Firebase's Realtime Database instead, which is more cost-effective when you have many small write operations. – Frank van Puffelen Jun 25 '20 at 14:32
  • I'm trying to implement what you answered below, today, I'm using Firebase Recycler Firestore, and for this type of data you don't pass a list to Recycler, but, yes, the Options Object, example: `options = new FirestoreRecyclerOptions.Builder () .setQuery (query, AnuncioPrincipal.class) .build (); adapter.updateOptions (options);` Does it still have how to change even using Options to update? – luke cross Jun 25 '20 at 14:37

2 Answers2

1

You can add a field to your AnuncioPrincipal that is not read from (or written to) Firestore:

public class AnuncioPrincipal {
    ...

    @Exclude
    public double distance

    ...
}

You can then set this (client-side only) field after you read the object from the DocumentSnapshot:

AnuncioPrincipal anuncioPrincipal1 = doc.getDocument().toObject(AnuncioPrincipal.class);
anuncioPrincipal1.distance = ...

And then you can use this new distance property to sort the items in the list that you show in the view, for example with: Sort ArrayList of custom Objects by property.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
0

After thinking for some hours i decided using this logical:

query.addSnapshotListener(new EventListener<QuerySnapshot>() {
@Override
public void onEvent(@Nullable QuerySnapshot documentSnapshots, @Nullable FirebaseFirestoreException e) {
for (DocumentChange doc : documentSnapshots.getDocumentChanges()){
if (doc.getType() == DocumentChange.Type.ADDED){
AnuncioPrincipal anuncioPrincipal1 = doc.getDocument().toObject(AnuncioPrincipal.class);
Location localAnuncioAtual = new Location("ProviderAun");

                                                    localAnuncioAtual.setLatitude(anuncioPrincipal1.getLatAnun());
                                                    localAnuncioAtual.setLongitude(anuncioPrincipal1.getLongAnun());
             anuncioPrincipal1.getCidadeAnunciante());
double distancia1 = Math.round(localizacaoUser.distanceTo(localAnuncioAtual)/1000);   // Distance in Km                                                 adapter.getItem(doc.getNewIndex()).setDistancia(distancia1); // SetDistance Between to Adapter
                                                    adapter.notifyDataSetChanged();
                                                }
                                            }
                                        }
                                    });

And to update the RecyclerView with local data (without hosted on Firestore Database), for it i created new Adapter with the data offline (cache) and i using this adapter on my recyclerView.setAdapter(adapter2), this work fine.

luke cross
  • 321
  • 1
  • 2
  • 19