imperiumlabs / GeoFirestore-Android

GeoFirestore for Android - Realtime location queries with Firestore

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Write only 1 time to Firestore

betegon opened this issue · comments

I followed the README , that writes the geopoint and geohash to an existing firestore document.

val collectionRef = FirebaseFirestore.getInstance().collection("ExistingCollectionUID")
val geoFirestore = GeoFirestore(collectionRef)
geoFirestore.setLocation("ExistingDocumentUID",GeoPoint(37.587,-122.405)){ exception ->
    if (exception != null){
        Log.d(TAG,"Location saved on server successfully!")
    }
}

The flow I am follow currently is:

  1. Write user info to a new document in Firestore

  2. Add GeoFirestore information to that document

This result in two writes into Firestore, doubling the price of the bill.

is there a way I can attach GeoFirestore information to the other document info and make only one write into Firestore?

Meaning that, I can store information to a variable and write it to firestore with the other data I have.

Thank you for your time and effort in GeoFirestore-Android.

Short answer: No
Long answer: The library didn't consider if the document was created two seconds ago or two years ago; hypothetically you can add geo-data to an old document.
I think that the typical use-case will be adding a new document along with with geo-data, so a method that let's add all in one go is well suited. I mark this issue as an enhancement hoping that someone will implement this functionality.

Perfect, I did a similar thing yesterday to try it out.

I created myself the g and l and then upload all the object to Firestore without using GeoFirestore. This will result in only one write, but it will also make people don't use GeoFirestore for that.

How do you see that functionality?
a) As a function that returns g and l so user can handle them as they want.
b) As a function that is given a hashmap and it adds to it g and l and upload all to Firestore (this will be 2 functions I guess)

I lean towards a).

Let me know what do you think about it, please.

I think there should be a function which takes your document POJO (or your map of fields) and your geo data, computes and adds g and l to it and upload all the document in one go

This could be a pseudocode

geoFirestore.addDocument(document, geoLocation) {
   l = get l (geoLocation)
   g = get g
   add g and l to document
   upload document to firestore
}

Hi @Supercaly , I have been thinking about your approach to this situation:

  1. If you accept a document (POJO or hashmap), it will be difficult to handle errors, due to the fact that Firestore only accept certain datatypes, meaning that it will cause an error if there is a datatype Firestore does not accept.

Here is an example

// Valid hashMap for Firestore
val docData = hashMapOf(
    "stringExample" to "Hello world!",
    "booleanExample" to true,
    "numberExample" to 3.14159265,
    "listExample" to arrayListOf(1, 2, 3),
    "nullExample" to null
)

// Invalid hashMap for Firestore
val docData = hashMapOf(
    "stringExample" to "Hello world!",
    "dateExample" to LocalTime(10,0)
)

Maybe I am taking a wrong approach, as I have less than a year of experience with Java/kotlin.

It is a good feature to develop because it will let you handle all Firestore related operations including Locations using GeoFirestore, which is pretty awesome.

Could you give a bit more explanation on this please?

Yeah, I forgot error handling
If I recall correctly the Firestore way of adding a document has a callback on failure, so our hypothetical method will take as argument a function (the on error callback), internally listen the firebase one and notify the user (who is listening to our callback) in case of some error.

in Kotlin the method declaration will be something like:

fun addDocument(document: Object, location: GeoLocation, onError: (e: GeoFirestoreError)->Unit)

Hi @betegon. I have the same problem but I have tried with firestore persistence enabled and it will result in just one read and one write with listener. However, when you switch the persistence to false, then you will be billed for 2 reads (the second due to the onDocumentChanged because of the second update to the initial doc) and 2 writes.

firestore.collection("my-collection").add(data).addOnCompleteListener(task -> {
                if(task.isSuccessful()){
                    String docId = task.getResult().getId();
                    geoFirestore.setLocation(docId, coordinates, e -> {
                        if(e == null){
                            Toast("Doc added successfully.");
                        }else{
                            Toast(e.getMessage());
                        }
                    });
                }else{
                    Toast(task.getException().getMessage());
                }
            });

Hi @cbarrios

If you have the same problem as me, what do you think of @Supercaly idea of a method like addDocument proposed in his latest comment?

As I am kind of a noob in kotlin, I don't know how to implement it, maybe if I look to you for guidance I could achieve it!

I will have a look at your code and I will come back to you.

Hi @cbarrios

If you have the same problem as me, what do you think of @Supercaly idea of a method like addDocument proposed in his latest comment?

As I am kind of a noob in kotlin, I don't know how to implement it, maybe if I look to you for guidance I could achieve it!

I will have a look at your code and I will come back to you.

Hi @betegon
I do think that having such a method is the correct way to go since the code I put works only if firestore cache persistence is enabled (which by default is). When set to false, then the code will still cost 2 writes.