RxFirestore getDocument() exists
Junderwood93 opened this issue · 5 comments
The RXFirestore getDocument() method currently returns a Maybe, but onSuccess is only called if the document exists.
I need this document to be returned regardless of whether it exists or not, as if it doesn't I need to create the document, but if it does I need to update it.
Hope this makes sense?
Hello @Junderwood93 .
if you want to do that. I recommend you to use a transaction. In that way you can check if the document exist and then do an operation based on that decision in an atomic way.
In other hand, you could also create the document if the Maybe
returns an onComplete
call and update it if the onSuccess
is called.
Both ways should resolve your problem. But I think that you should go for a transaction.
Thanks for getting back to me!
I can't use transactions because they fail when offline.
On your other suggestion, I did consider this but couldn't figure out how to check if onComplete was called without onSuccess being called in the middle of an RX chain.
I guess what I'm trying to build is something that works like this, but without having to use transactions:
getDoc(ref)
.onEmptyReturn( () -> setDoc(ref, docData)
.andThen(getDoc(ref))
.map( doc -> {
..
}
But as far as I can tell, onEmptyReturn isn't a thing.
Just onSuccess
or onComplete
will be called. Never both of them. the library follows the MaybeObserver
contract:
After a MaybeObserver calls a Maybe's subscribe method, first the Maybe calls onSubscribe(Disposable) with a Disposable that allows cancelling the sequence at any time, then the Maybe calls only one of the MaybeObserver's onSuccess(T), onError(java.lang.Throwable) or onComplete() methods to provide notifications.
You can read more about it here:
http://reactivex.io/RxJava/javadoc/io/reactivex/MaybeObserver.html
If you want to use it on a RxChain. I suggest you to wrap it using a toSingle(defaultValue)
For example:
getDoc(ref)
.map( snapshot -> snapshot.exists())
.toSingle(false) //By default it will be false because the map will just happend if the snapshot exists
.subscribe()
Anyway, seeing your implementation. You don't need to do a set
and later a get
. If you can do a set
it means that you have the data that you want to retrieve from the database already. So there is no need to go for that andThen
. You are doing an extra call without no reason.
I would do something like:
RxFirestore.getDocument(ref)
.map { it.toObject(MyClass::class.java) }
.subscribeOn(Schedulers.io())
.subscribe(
{ myData -> doSomethingWithMyData() },
{ error -> manageError(error) }, {
{
updateDataAsync(defaultDocValue) //this will do the setDoc
doSomethingWithMyData(defaultDocValue)
}
})
You can also use doOnComplete
to set the document and doOnSuccess
to update it.
RxFirestore.getDocument(ref, MyClass::class.java)
.doOnComplete { setDoc() }
.doOnSuccess { updateDoc() }
.subscribe({ data ->
doSomethingWithMyData(data)
}, { error ->
manageError(error)
}, {
doSomethingWithMyData(defaultDocValue)
})
This is great, thanks so much for taking the time to explain it! RX is still pretty new to me.
You welcome! Feel free to ask whatever you need !