Get random entries in firebase real-time database - firebase

This is my code to get 5 items from realtime database:
val database = FirebaseDatabase.getInstance()
val brandReference = database.getReference("brandGame").limitToFirst(5)
brandReference.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
dataSnapshot.children.forEach {
...
}
}
}
And this is how my real-time database looks like:
What's the best way to get 5 items randomly? I know there isn't a random function in real time database yet.

If you know the number of elements in the brandGame/-reference, you could pick 5 random numbers between 1 and numberOfElements and retrieve those. This would result in multiple calls to the database.
Alternatively, you could download everything from the brandGame/-reference and just pick 5 random elements using pure Kotlin. But then you must download everything in the reference, which could be a lot.
The best option is to set up a cloud function that does the "pick 5 random options"-logic server side. https://firebase.google.com/docs/functions/ But this requires that you write some js :)
As you say, there is no built-in way to get random elements from a reference.

To get a random brand, please use the following code user side:
val rootRef = FirebaseDatabase.getInstance().reference
val brandGameRef = rootRef.child("brandGame")
val valueEventListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val brandCountList = ArrayList<String>()
for (ds in dataSnapshot.children) {
val brand = ds.child("brand").getValue(String::class.java)
brandCountList.add(brand!!)
}
val brandCount = brandCountList.size
val randomNumber = Random().nextInt(brandCount)
val randomBrand = ArrayList<String>()
randomBrand.add(brandCountList.get(randomNumber)) //Add the brand product to list
val arrayAdapter = ArrayAdapter(applicationContext, android.R.layout.simple_list_item_1, randomBrand)
list_view.adapter = arrayAdapter
}
override fun onCancelled(databaseError: DatabaseError) {
//Handle exceptions
}
}
brandGameRef.addListenerForSingleValueEvent(valueEventListener)

Related

Retrieving data from push() in firebase kotlin that equal to the selected value

Hello can someone that can help me to retrieve the data of selected value from generate key or push in Realtime Database Firebase. Nothings happen when I clicking the button I think my child is not order correctly. This is the collection tree from firebase;
val btnSyncing = findViewById<TextView>(R.id.btnSync)
btnSyncing.setOnClickListener {
val user = FirebaseAuth.getInstance().currentUser
val userid = user!!.uid
database = FirebaseDatabase.getInstance()
reference = database.getReference("Profile")
val timeTextView = findViewById<TextView>(R.id.txtTime)
val dateTextView = findViewById<TextView>(R.id.txtDate)
reference.child(userid)
.child("Delivery Details").orderByChild("Date").equalTo("24/9/22")
.addListenerForSingleValueEvent(object: ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val time = dataSnapshot.child("Time").value as String?
val date = dataSnapshot.child("Details").value as String?
timeTextView.text = time
dateTextView.text = date
}
override fun onCancelled(error: DatabaseError) {
Toast.makeText(baseContext, "Something wrong happened!", Toast.LENGTH_LONG)
.show()
}
})}

How to sum of values from Firebase Database in Kotlin?

I have a Firebase Database with several purchases in Android app, points value is assigned for each purchase, then entries are showing by following way:
When userId is log in, a button appears and when user click on it the "showInfoClient" function is called and it must show user and the amount of points. Code is:
private val database = Firebase.database
private val myref = database.getReference("compras")
fun showInfoClient(view: View) {
val userlog = FirebaseAuth.getInstance().currentUser?.displayName
val alertDialogInfo = AlertDialog.Builder(this).create()
myref.orderByChild("userId").equalTo(userlog).addListenerForSingleValueEvent(object :
ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
var sum = 0
for (data in dataSnapshot.children) {
sum += data.child("puntos").getValue(Int::class.java)!!
Toast.makeText(this#Principal, sum, Toast.LENGTH_SHORT).show()
}
}
override fun onCancelled(databaseError: DatabaseError) {}
})
alertDialogInfo.setTitle(userlog)
alertDialogInfo.setMessage("Puntos: ") // + sum
alertDialogInfo.setButton(
AlertDialog.BUTTON_POSITIVE, "OK"
) { dialog, _ ->; dialog.dismiss() }
alertDialogInfo.show()
val btnPositive = alertDialogInfo.getButton(AlertDialog.BUTTON_POSITIVE)
val layoutParams = btnPositive.layoutParams as LinearLayout.LayoutParams
layoutParams.weight = 100f
btnPositive.layoutParams = layoutParams
}
I have tried to use different options but i´m not able to set "sum" value on
alertDialogInfo.setMessage("Puntos: $sum")
Thanks in advance
Any code that needs data from the database needs to be inside onDataChange or be called from there. Code outside of onDataChange will (most likely) run before the data is loaded.
So:
val userlog = FirebaseAuth.getInstance().currentUser?.displayName
val alertDialogInfo = AlertDialog.Builder(this).create()
myref.orderByChild("userId").equalTo(userlog).addListenerForSingleValueEvent(object :
ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
var sum = 0
for (data in dataSnapshot.children) {
sum += data.child("puntos").getValue(Int::class.java)!!
}
alertDialogInfo.setTitle(userlog)
alertDialogInfo.setMessage("Puntos: ") // + sum
alertDialogInfo.setButton(
AlertDialog.BUTTON_POSITIVE, "OK"
) { dialog, _ ->; dialog.dismiss() }
alertDialogInfo.show()
val btnPositive = alertDialogInfo.getButton(AlertDialog.BUTTON_POSITIVE)
val layoutParams = btnPositive.layoutParams as LinearLayout.LayoutParams
layoutParams.weight = 100f
btnPositive.layoutParams = layoutParams
}
override fun onCancelled(databaseError: DatabaseError) {
throw databaseError.toException(); // never ignore errors
}
})
For a longer explanation see:
getContactsFromFirebase() method return an empty list
Setting Singleton property value in Firebase Listener

How to read and filter entities-aggregates based on condition in Axon and after that change them

I am new with Axon and maybe I missed something, but need help to understand.
I have a simple food cart aggregate.
Here is example:
#Aggregate
class FoodCard {
#AggregateIdentifier
private lateinit var foodCardId: UUID
private lateinit var selectedProduct: MutableMap<UUID, Int>
constructor()
#CommandHandler
constructor(command: CreateFoodCartCommand) {
AggregateLifecycle.apply(FoodCartCreateEvent(
UUID.randomUUID()
))
}
#CommandHandler
fun handle(command: SelectProductCommand) {
AggregateLifecycle
.apply(ProductSelectedEvent(foodCardId, command.productId, command.quantity))
}
#CommandHandler
fun handle(command: DeleteFoodCartCommand) {
AggregateLifecycle
.apply(FoodCartDeleteEvent(foodCardId))
}
#CommandHandler
fun handle(command: DeselectProductCommand) {
val productId = command.productId
if (!selectedProduct.containsKey(productId)) {
throw ProductDeselectionException("ProductDeselectionException")
}
AggregateLifecycle
.apply(ProductDeselectEvent(foodCardId, productId, command.quantity))
}
#EventSourcingHandler
fun on(event: FoodCartCreateEvent) {
foodCardId = event.foodCardId
selectedProduct = mutableMapOf()
}
#EventSourcingHandler
fun on(event: ProductSelectedEvent) {
selectedProduct.merge(
event.productId,
event.quantity
) {a, b -> a + b}
}
}
As ES I am using Axon Server.
For FoodCard projector I am using JPA repository that connects to DB.
I want to get all foodcards that contain special product (concrete UUID) and change quantity to -1 for all of them.
I understood there are two types of actions -> read and write
So the question how to correctly implement this flow with Axon?
Thanks
from your explanation and code I feel that you will probably need to complete your implementation of DeselectProductCommand introducing an EventSourcingHandler for ProductDeselectEvent. If I understood correctly your "quantity" information is stored into the selectProduct Map. In this case, based on your code, I see that the information of the quantity that should be subtracted to your product is in the command.
You will also need a Query, such as FindAllFoodCardByProductId, that will retrieve the foodCardId aggregate identifier that contains a certain productId: this operation will be performed on your Projection through the jpa repository.
As a reference you can have a look at the ref guide here https://docs.axoniq.io/reference-guide/implementing-domain-logic/query-handling on how to use QueryGateway into your controller and implement a QueryHandler into your Projection.
Corrado.

Firebase query equalTo() or startAt().endAt() stop working

I already tried suggestions from other posts but no success.
I just run into an issue,I got the following code which displays data from Firebase database when user clicks on a specific date.If I comment out (startAt(),endAt()), the recycler gets populated with all data, when I add equalTo() or startAt().endAt()) recycler does not get populated.
The code before was working normally, just recently stopped working and I have no clue why.
The code looks like this:
Bellow is the adapter:
fun calendarAdapt(options:FirebaseRecyclerOptions<ModelCalendar>,dataref:
DatabaseReference,context: Context):FirebaseRecyclerAdapter<ModelCalendar,CalendHold>{
return object :FirebaseRecyclerAdapter<ModelCalendar,CalendHold>(options){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CalendHold {
return
CalendHold(LayoutInflater.from(parent.context).inflate(R.layout.list_row_calendar,parent,false))
}
override fun onBindViewHolder(holder: CalendHold, positionc: Int, modelc: ModelCalendar)
{
val postkeyC= getRef(positionc).key
dataref.child(postkeyC!!).addValueEventListener(object:ValueEventListener{
override fun onDataChange(dataSnapshot: DataSnapshot) {
holder.bindlogC(modelc)
}
override fun onCancelled(p0: DatabaseError) {
}
})
}
}
}
This is the Query:
fun query2(cont: LifecycleOwner,selected_date:String):FirebaseRecyclerOptions<ModelCalendar>{
val queryy = FirebaseDatabase.getInstance()
.reference
.child("Ev")
.startAt(selected_date)
.endAt(selected_date)
return FirebaseRecyclerOptions.Builder<ModelCalendar>()
.setQuery(queryy,ModelCalendar::class.java)
.setLifecycleOwner(cont)
.build()
}
Here I apply the adaptor:
mDb = FirebaseDatabase.getInstance().reference.child("Ev")
val c = Calendar.getInstance()
val year2 = c.get(Calendar.YEAR)
val month2 = c.get(Calendar.MONTH)
val day2 = c.get(Calendar.DAY_OF_MONTH)
val dayd= checkDigit(day2)
val monthd= checkDigit(month2+1)
val datetoday = java.lang.StringBuilder()
.append(dayd)
.append("-")
.append(monthd)
.append("-")
.append(year2)
calendinf(datetoday.toString())
calendarid.setOnDateChangeListener { view, year, month, dayOfMonth ->
val month = checkDigit(month+1)
val day = checkDigit(dayOfMonth)
val datesel =StringBuilder()
.append(day)
.append("-")
.append(month)
.append("-")
.append(year)
calendinf(datesel.toString())
}
}
private fun calendinf(selected_date:String){
val options = Queryess().query2(this,selected_date)
val adaptorC = Adaptall().calendarAdapt(options, mDb,this)
calerec!!.adapter=adaptorC!!
}
I fix-it,It was the query, was missing "orderBychild()" field, most probable I mistakenly deleted otherwise cannot explain-it :))

How to deserialize number value in Firestore field and read this inside de while/loop using kotlinx.coroutines

In the firestore I created a field named PararUm, type number (it does not have Int, when I enter it manually) and I put value 1.
The problem is that the return has been PararUm(PararUm=1) and not just 1.
(99-below)
When I resolved this, I would have solved the first part of the project.
Regarding the second, I want to use kotlinx.coroutines to work within a while/loop (which queries the value of the PararUm field) in a synchronous, non-asynchronous way (as firebase requires)
Can I do something like???(999-below):
I threw this topic down, but I was not happy1.
99-below:
model
#IgnoreExtraProperties
data class PararUm(
var PararUm: Int? = 0
)
Activity
var db = FirebaseFirestore.getInstance()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var pararumRef =
db.collection("smartmodel").document("xxxxxxxxxxxx")
pararumRef.get().addOnSuccessListener { documentSnapshot ->
var PararUm = documentSnapshot.toObject(PararUm::class.java)
Log.i(ContentValues.TAG, "1999 1999 1999" + PararUm)
}
}
999-below:
while (!FCMotorUmA.value) {
var snapshot = pararumRef.get().await()
    
var pararum = snapshot.toObject(PararUM::class.java)
if (pararum.equals(0)) {
// Do something 1
} else if (pararum.equals(1)) {
// Do something 2
}
}

Resources