Is there a way to retrieve realtime firebase map as a linkedhashmap or at least maintain the order it is saved in - firebase

I have a map of string boolean pairs saved on firebase realtime database and was wondering if there is a way to retrieve it in kotlin as a linkedhashmap such that the original order remains in place.
I have tried typecasting to a linkedhashmap and got an error that hashmap cannot be typecasted to linked hashmap, I then tried calling the linkedhashmap constructor method with the parameter being the data from the database as a hashmap but that does not maintain the order

Properties in JSON are by definition not in any specific order.
While you can retrieve data from Firebase in a specific order, by calling one of its orderBy... operations, that order will be lost when you call .value in the DataSnapshot as DataSnapshot.value returns a Map, which is unordered again.
If you want to retrieve the nodes in a specific order:
Call orderBy... to get the nodes in a specific order.
Loop over the children of the snapshot you get back to process them in order, and only call value on each specific child node.

Related

Firebase search by child value KOTLIN

This is my firebase realtime database structure
I want to retrieve all questions with QID = "PQ1" . What i tried is given below . Its result is null .
database.child("Question").child("QID").equalTo("PQ1").limitToFirst(200).get().addOnSuccessListener {
Log.i("12345", "Got value ${it.value}")
}
My references :
Firebase - Search a child by value
Firebase search by child value
Search firebase by Child of child value
Your call to database.child("Question").child("QID") looks for a child node at path /Question/QID in your database, which doesn't exist and thus explains why you get an empty snapshot.
To query the Firebase Realtime Database needs two steps:
You order all child nodes on a property, on their key, or on their value by calling on of the orderBy... methods.
You then filter the ordered child nodes by calling one or more of the equalTo, startAt, startAfter, endAt, endBefore, limitToFirst and/or limitToLast methods.
While you're doing #2, you're not ordering the nodes first by calling orderBy....
The correct code:
database.child("Question").orderByChild("QID").equalTo("PQ1").limitToFirst(200).get().addOnSuccessListener {
Log.i("12345", "Got value ${it.value}")
}
Also don't forget that executing a query will potentially have multiple results, so the snapshot in it.value contains a list of those results and you will need to iterate over its children. Even if there is only a single result, the snapshot will contain a list of one result.

firestore map key-value pairs randomly change order when retrieved from the database

I have a button which runs the following code when it's clicked:
let dataReference = await db.collection("dog").doc("1").get()
let HashMap = dataReference.data().Annotations
console.log(HashMap)
My firestore database looks like this:
Whenever this function is run, it returns the proper dictionary, however, the ordering of the keys seems to change randomly. Here's a screenshot of my console logs when I pressed the button a bunch of times:
Why does the ordering of the key-value pairs change and is there a way to fix it?
The Firestore SDK does not guarantee an order of iteration of document fields. What you see in the console is always lexically sorted by the code of the console itself. If you require a stable ordering, you should sort them yourself before iteration.
One workaround you can do is to have the order of the keys you want in an array. Because arrays are ordered it will maintain the order you desired. Then you take that key and use it in the dictionary. While the dictionary is out of order, you will be accessing each value in order by key.

Is it possible to query an element in Firestore by key without knowing which collection it belongs to?

Using AngularFire2, Angular, Firebase Firestore, and one of my records models the relationship between a user and different types of objects.
/*
Represents a reaction that a user has towards some object in the system.
*/
export interface Reaction{
// The id of the user making that reaction
userId? : string;
// The id of the object that is being reacted to. Place, Org, List, Offer
objectId? : string;
}
As you can see the only thing being stored is the key of an object and not its type or which collection it belongs to. I'm wondering how it would be possible at a later time, to query the reactions and then from there get the objects purely based on their key?
You must know the name of the collection (and possibly subcollection) of a document in order to obtain it. There's no concept of a query that can get a document without knowledge of a collection.

How do I stop Firebase from creating an additional nested object or how can I access the newly generated string?

Problem: Whenever I add an order to the orders array, an additional nested array element(-KOPWA...) gets added. I wouldn't mind except, I don't know how to access that nested string to access it's child nodes.
Example of database node for users below:
firebase.database().ref('users/'+userIdState+'/orders/'+<<unique numbervariable>>).push({
"order":{"test":"product","quantity":2}
});
I'm using the above code to push new json objects with a unique number to the firebase array. Still the nested array with the weird strings gets generated.
Can anyone help me understand how to either: create my own nested array with my own unique string or how to access the nested string that gets generated from firebase so I can access it's children nodes.
Multiple instances of nest arrays will be generated by users.
Any help is much appreciated.
Thanks,
Moe
You're experiencing this behaviour because Firebase's push is not the same as an array push. I recommend reading this article to understand how it works.
As for a solution, you can simply change push to set in your code. This will create the structure you were (presumably) expecting, that is
1:
order:
...
This is however potentially unsafe, if you allow concurrent writes (i. e. if the "unique number" in your example is not always unique).
Afaik Firebase recommends using push to safely create collections/"arrays". You can retrieve the generated key by calling the key property on the reference returned by push. Like this:
var ref = firebase.database().ref('users/'+userIdState+'/orders/'+<<unique numbervariable>>).push({
"order":{"test":"product","quantity":2}
});
var generatedKey = ref.key; // the value you're looking for
If you decide to use it, you can probably just drop the order number you have right now and just use the generated one.

In Firebase whats the difference between push and childByAutoId

In Firebase if I'd like to create a child node with a unique ID it appears I have two options:
Push() :
Use the push() method to append data to a list in multiuser
applications. The push() method generates a unique ID every time a new
child is added to the specified Firebase reference. By using these
auto-generated keys for each new element in the list, several clients
can add children to the same location at the same time without write
conflicts. The unique ID generated by push() is based on a timestamp,
so list items are automatically ordered chronologically.
childByAutoId:
childByAutoId generates a new child location using a unique key and
returns a FIRDatabaseReference to it. This is useful when the children
of a Firebase Database location represent a list of items. The unique
key generated by childByAutoId: is prefixed with a client-generated
timestamp so that the resulting list will be chronologically-sorted.
Whats the difference?
Nevermind, it appears they are the same except they cater to different platforms:
Save Data on IOS
childByAutoId : Add to a list of data. Every time you call childByAutoId, Firebase generates a unique ID, such as user-posts/<user-id>/<unique-post-id>.
Save Data on Web
push() : Add to a list of data. Every time you call push(), Firebase generates a unique ID, such as user-posts/<user-id>/<unique-post-id>.

Resources