I have data structure as:
https://law-apps-44h221543638e.firebaseio.com/apps to promote/0/ >> name:"First App", package:"fra"
https://law-apps-44h221543638e.firebaseio.com/apps to promote/1/ >> name:"Second App", package:"sca"
https://law-apps-44h221543638e.firebaseio.com/apps to promote/2/ >> name:"Third App", package:"tha"
and I query it using
Firebase myFirebaseReference = new Firebase("https://law-apps-44h221543638e.firebaseio.com/apps to promote");
Query queryRef = myFirebaseReference.orderByChild("name");
queryRef.addListenerForSingleValueEvent(new ValueEventListener() { // override methods })
But it returns the data in the same order i.e sorted by the first child (1,2,3, etc.)
How should I query it so it sorts the data by the "name" tag of each child?
Ok so I found the answer to this question and I am writing it so others may benefit from it. I was using an older technique wherein I was finding from datasnapshot my apps using their parents' numbers and due to this, I was delibrately undoing the ordering.
Now I have used dataSnapshot.getChildren().iterator() and it is now working correctly. Here's the code:
Query queryRef = myFirebaseReference.orderByChild("name");
queryRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String name;
String my_package;
long lengthOfForLoop = dataSnapshot.getChildrenCount();
Iterator<DataSnapshot> child = dataSnapshot.getChildren().iterator();
for (int i = 0; i < lengthOfForLoop; i++) {
DataSnapshot next = child.next();
name = next.child("name").getValue(String.class);
my_package = next.child("package").getValue(String.class);
// do something with this data.
}
}
});
}
thanks, Usman!
I used the same code with the children iterable collection in a for loop.
This code was worked for me (in Kotlin):
accountsReference.child(accountId).child("actions").orderByChild("actionPosition").addListenerForSingleValueEvent( object : ValueEventListener {
override fun onDataChange(var1: DataSnapshot) {
if (var1.children != null) {
for (actionsEntries in var1.children) {
...
}
}
Related
I have a database something like this. How I want to compare the value for all users to get most value.
restaurant
-userUid
-stateUid
-restaurantUid
-price = 9
-restaurantUid2
-price = 10
-stateUid2
-restaurantUid3
-price = 2
As you can see the database there, stateUid price is 19 while stateUid2 price is only 2
So, stateUid has the most price. How to compare them and display the most one. Thank you
EDIT:
I have done something like this, and it's error at return. And the value is not working.
exports.calculateTotal = functions.database.ref('/restaurant/{userUid}/{stateUid}/{restaurantUid}')
.onWrite((change, context) => {
// Only edit data when it is first created.
if (change.before.exists()) {
return null;
}
// Exit when the data is deleted.
if (!change.after.exists()) {
return null;
}
//Get id
const restaurantUid = context.params.restaurantUid;
let totalValue = 0;
change.after.forEach(function (item) {
totalValue += item.child('total').val();
});
console.log(totalValue);
return functions.database.ref('/priceTotal/' + restaurantUid).child('total').set(totalValue);
});
Firebase queries work on a flat list of nodes. A query can contain only a single unknown key, the key of the direct child nodes under the location where you query. In your data structure there are multiple levels of unknown keys, which means that you can't query for the highest price across all of them.
What you can do in your current data structure is query across one state for the restaurant with the highest price. That'd look something like:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("restaurant");
DatabaseReference stateRef = ref.child("userUid").child("stateId");
stateRef.orderByChild("price").limitToLast(1).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot: dataSnapshot.getChildren()) {
Log.i(TAG, snapshot.getKey()+": "+snapshot.child("price").getValue(Long.class));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
}
But you can't search across all states for a user, or even all users. If you want to allow that, you'll have to store all prices in a flat list, like:
restaurant_prices: {
"restaurantid": {
price: 9,
state: "statid",
user: "userid"
}
}
Also see:
Firebase Query Double Nested
Firebase query if child of child contains a value
int totalPrice = 0;
int greaterPrice = 0;
int temp = 0;
DatabaseRefernce restRef = FirebaseDatabase.getInstance().getReference().child("restaurant").child(userUid);
restRef.addValueEventListener(new ValueEventListener(){
onDataChange(Datasnapshot snapshot) {
for(Datasnapshot snap : snapshot) {
String key = snap.getKey();
//This will return you the keys of stateUid
restRef.child(key).addValueEventListener(new ValueEventListener(){
onDataChanged(DatSnapshot datasnapshot) {
//this for loop will iterate through restaurants of that specific state
for(DataSnapshot snap2 : datasnapshot){
totalPrice += (int) snap2..child("price").getValue();
}
//When this loop ends you will get the total price of all restaurants from that state
}
});
//as u see above I mentioned greater price and temp variable
using simple logic of finding greatest number out of two number save the value of greatest integer to the variable every time you loop through state
}
}
}
);
Use nested for loops to iterate from database like above and calculate your prices
Else what you can do is when you are uploading the data of restos - while uploading prices just make an extra node for total price of city and add price of resto every time you upload new resto
I need to get the string value from the node passcode in my Firebase database to compare with a user input, but unfortunately I am not able to get the value. This is the link to my firebase database in the below image.
This is my codes below:
final DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference("pin_code");
mDatabase.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
#Override
public void onDataChange(com.google.firebase.database.DataSnapshot dataSnapshot) {
String rface = (String) dataSnapshot.child("pincode").getValue();
if (rface.equals(userPassword) && !rface.equals("")){
Intent intent = new Intent(PinActivity.this, ProfileActivity.class);
startActivity(intent);
}
else {
if (rface.equals("") || rface.equals(null)){
// Creating new user node, which returns the unique key value
// new user node would be /users/$userid/
String userId = mDatabase.push().getKey();
// creating user object
Pin pin = new Pin(authUserId, userPassword);
mDatabase.child(userId).setValue(pin);
Intent intent = new Intent(PinActivity.this, ProfileActivity.class);
startActivity(intent);
}
else {
Toast.makeText(PinActivity.this,"Invalid PIN code", Toast.LENGTH_SHORT).show();
return;
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
This is the json code
{
"pin_code" : {
"id" : "TQYTo1NHNnhPJnOxhe1Vok3U6ic2",
"pincode" : "12345"
}
}
This FirebaseDatabase.getInstance().getReference("pin_code") does not refer to the node you're looking for. Most likely you know the id property, in which case you can get the node with:
DatabaseReference collection = FirebaseDatabase.getInstance().getReference("p...");
Query query = collection.orderByChild("id").equalTo("TQT...ic2");
query.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
#Override
public void onDataChange(com.google.firebase.database.DataSnapshot dataSnapshot) {
for (DataSnapshot child: dataSnapshot.getChildren()) {
String rface = (String) child.child("pincode").getValue();
if (rface.equals(userPassword) && !rface.equals("")){
The changes I made:
On the first line we get the collection: the node under which you want to run a query. You struck out the name of that node in the screenshot, but it's the second line you marked.
In the second line we create a query on the id property of each child node under the collection.
In the onDataChange we added a loop. This is needed because a query against the Firebase Database will potentially have multiple results. So the dataSnapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result. We loop over dataSnapshot.getChildren() to handle those multiple results.
If there can ever only be one node with the same id, you should consider changing your data structure to use the id as the key of the node. So:
pin_codes
uid1: "pincode1"
uid2: "pincode2"
Your code then becomes significantly simpler, because you don't need to query for the user anymore. You can just directly read from the path:
DatabaseReference user = FirebaseDatabase.getInstance().getReference("pin_codes").child("TQT...ic2");
user.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
#Override
public void onDataChange(com.google.firebase.database.DataSnapshot dataSnapshot) {
String rface = (String) dataSnapshot.getValue();
if (rface.equals(userPassword) && !rface.equals("")){
Try change this:
String rface = (String) dataSnapshot.child("pincode").getValue();
To this:
String rface = (String) dataSnapshot.child("pincode").getValue(String.class);
Use the following::
Object some = dataSnapshot.getValue();
String value = some.toString();
I have stored ArrayList in firebase DB, is there any way to get specific record from firebase using particular id (memberId) from ArrayList
Currently, I'm able to get the tripMemberList ArrayList but I want to get specific record from ArrayList using memberId
I don't want to retrieve full ArrayList only need a single record from tripMemberList using memberId
I'm attaching a firebase DB structure below
Edit: How i add a record to firebase
TripChatDTO tripChatDTO = new TripChatDTO();
tripChatDTO.setTripId(jsonObject.getInt("travelId"));
tripChatDTO.setTripName(travelDTO.getTitle());
tripChatDTO.setTripPicUrl(jsonObject.getString("image"));
List<TripMemberDTO> memberDTOList = new ArrayList<>();
for (int i = 0; i < invitedFriendArray.length(); i++) {
JSONObject jsonObject1 = invitedFriendArray.getJSONObject(i);
TripMemberDTO dto = new TripMemberDTO();
dto.setMemberId(jsonObject1.getInt("id"));
dto.setAdmin(false);
dto.setNotification(true);
memberDTOList.add(dto);
}
// Add Admin record
TripMemberDTO tripMemberDTO = new TripMemberDTO();
tripMemberDTO.setMemberId(loggedInUser.getId());
tripMemberDTO.setAdmin(true);
tripMemberDTO.setNotification(true);
memberDTOList.add(tripMemberDTO);
// Add all Member record to travel
tripChatDTO.setTripMemberList(memberDTOList);
String channelName = "Trip-" + tripChatDTO.getTripId();
// Create tip
FirebaseDatabase.getInstance().getReference().child(TRIP).child(channelName).setValue(tripChatDTO);
it might be anywhere in the list I want to find a record using `memberId
Then loop over the children of the top element
tripMemberRef rootRef = FirebaseDatabase.getInstance().getReference()
.child("Trips/Trip-190/tripMemberList");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot c : dataSnapshot.getChildren()) {
String memberId = c.child("memberId").getValue(String.class);
Log.d("TAG", memberId);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
ref.addListenerForSingleValueEvent(eventListener);
Assuming that Trips is a direct child of the Firebase root, please use this code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = rootRef.child("Trips").child("Trip-190").child("tripMemberList").child("0");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String memberId = dataSnapshot.child("memberId").getValue(String.class);
Log.d("TAG", memberId);
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
ref.addListenerForSingleValueEvent(eventListener);
But remember, Firebase is a NoSQL database which is structured as pairs of key and values. This means that every object within a Firebase database is a Map and not an ArrayList.
I'm running into a weird issues in which a Firebase query using orderByChild() doesn't actually order the data. Below is a snapshot of the data that I'm trying to order: (total is off for the sake of this example)
This is the code that I've used so far:
Query query = locationComment.orderByKey();
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue() == null) {
return;
}
data.clear();
adapter.notifyDataSetChanged();
String userId;
String time;
String comment;
Map<String, String> commentMap = (Map) dataSnapshot.getValue();
for (Map.Entry<String, String> entry : commentMap.entrySet()) {
if(!((entry.getKey()).contains("total"))) {
String[] keyString = (entry.getKey()).split(",");
time = keyString[0];
userId = keyString[1];
comment = entry.getValue();
Date resultdate = new Date(Integer.parseInt(time));
data.add(new Comment(comment,
DateFormat.getDateTimeInstance().format(resultdate), userId));
adapter.notifyItemInserted(data.size());
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I'm getting each and every key-value pair (barring total) except that it's not in order as expected (ordered by key). The Firebase docs say that the keys are ordered lexicographically if they can't be parsed into a 32 bit integer.
Either way though the order should be as shown in the image but the data that I get back while looping through the map is not in this order.
I would really appreciate it if someone could point me in the right direction. Thanks!
When you execute a query you get three things:
they keys
the values
the relative order between these
When you convert the result to a Map it can only hold two of these, so the order is lost. To prevent this, you should use the DataSnapshot.getChildren() method:
Query query = locationComment.orderByKey();
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue() == null) {
return;
}
data.clear();
for (DataSnapshot child : dataSnapshot.getChildren()) {
...
}
adapter.notifyDataSetChanged();
}
Also see this example in the Firebase documentation on working with lists: https://firebase.google.com/docs/database/android/lists-of-data#listen_for_value_events
Looks like your data is badly structured.
Firebase has it's internal way of keying, and Firebase only can order those keys, with additional criteria if wanted. But since your key, is a custom key, firebase can't and won't order this branch.
The solution is to restructure your data in a meaningful way, like this
+ comments
+ total: 13
+ data:
+ 12uoasjihdou3
+ time: xx
+ userID: xx
+ comment: xx
+ 123tjiueoi134
+ 1piahf9hasheui
+ 6890324890oiuwer
Always use push() to generate new keys, do not create custom keys for lists, thats a total no go
FirebaseDatabase.getReference("comments").child("data").push({yourdata});
if you want to order your data, this is how you do that
FirebaseDatabase.getReference("comments").child("data").orderByChild("time");
Instead of setting the data to null from the child of table Driver.. I want that specific child to be removed.
Here is my sample code.
driverRef = new Firebase(Config.FIREBASE_URL_DRIVER);
Query pendingBus = driverRef.orderByChild("busNum").equalTo(busNum);
pendingBus.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
String busnumber = snapshot.child("busNum").getValue().toString();
String empID = snapshot.child("empId").getValue().toString();
if (busnumber.equals(busNum)) {
snapshot.getRef().child("age").setValue("");
snapshot.getRef().child("busNum").setValue("");
snapshot.getRef().child("driversName").setValue("");
snapshot.getRef().child("empId").setValue("");
snapshot.getRef().child("latitude").setValue("");
snapshot.getRef().child("longitude").setValue("");
snapshot.getRef().child("password").setValue("");
snapshot.getRef().child("username").setValue("");
}
}
and this is the output of that method setValue
Instead of using setValue to null
I use .removeValue
Example: snapshot.getRef().child("age").removeValue();
this is worked for me
databaseReference = databaseReference.child("Users").child(mobile);
databaseReference.setValue(null);