Get index data with setIndexedQuery where index not end of path - java

I have a Firebase realtime database with a layout similare to this:
{
"data": {
"index_1": {
"xxx": {
"value_1": "Some data",
"value_2": true
},
"index_2": {
"xxx": {
"value_1": "Some data",
"value_2": true
},
"index_3": {
"xxx": {
"value_1": "Some data",
"value_2": true
},
},
"keys": {
"user1": {
"index_1": true,
"index_2": true
},
"user2": {
"index_1": true,
"index_3": true
}
}
}
And a simple java class:
public class Data {
private String value_1;
private Boolean value_2;
...
getters/setters
...
}
Is there any (easy) way to get objects from /data/{index}/xxx/{object}?
If the layout had been /data/{index}/{object}, eg:
"data": {
"index_1": {
"value_1": "Some data",
"value_2": true
}
}
it's is possible to use
keyQuery = FirebaseDatabase.getInstance()
.getReference("keys")
.orderByKey();
dataRef = FirebaseDatabase.getInstance().getReference("data");
FirebaseRecyclerOption<Data> options = new FirebaseRecyclerOptions.Builder<Data>().
.setIndexedQuery(keyQuery, dataRef, Data.class)
.build();
but I havn't found any way to do this when the index isn't just before the wanted data.

I found a way to solve it using FirebaseRecyclerOption by creating a custom SnapshotParser
SnapshotParser<Data> parser = new SnapshotParser<Data>() {
#NonNull
#Override
public Data parseSnapshot(#NonNull DataSnapshot snapshot) {
return snapshot.child("xxx").getValue(Data.class);
}
}
FirebaseRecyclerOption<Data> options = new FirebaseRecyclerOptions.Builder<Data>().
.setIndexedQuery(keyQuery, dataRef, parser)
.build();

Is there any (easy) way to get objects from /data/{index}/xxx/{object}?
Yes it is, using the following lines of code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference dataRef = rootRef.child("data");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String value_1 = ds.child("xxx").child("value_1").getValue(String.class);
boolean value_2 = ds.child("xxx").child("value_2").getValue(Boolean.class);
Log.d(TAG, value_1 + " / " + value_2);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
}
};
dataRef.addListenerForSingleValueEvent(valueEventListener);
If you want to use FirebaseRecyclerOption, you database schema should indeed looks like this:
"data": {
"index_1": {
"value_1": "Some data",
"value_2": true
}
}
Without that extra xxx child.

Related

Reading data from firebase realtimedatabase

I am writing data to the database using another class with a constructor, but I still need to read data from the database. In the documentation, when using other classes, you need to create HashMap lists for each element, but I have 2 classes (since I need to write more than 255 entries to the database) and in each class, I will have to write a HashMap. How can I load the name of a DB variable that is identical to the name in the file itself? For example int b = 0; and in the database - b: 0 and how can you get the value of each variable from the database?
I send data like this:
if (user != null) {
if(database.child(getEmail)==null) {
User newUser = new User(getEmail, coins, ....);
User1 newUser1 = new User1(a256, a257, ....);
database.child(getEmail).push().setValue(newUser1);
database.child(getEmail).push().setValue(newUser);
}
I read data like this:
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for(DataSnapshot ds : snapshot.getChildren()){
User user = ds.getValue(User.class);
//saving information witch will read from db in SharedPreferences
PreferenceConfig.GetEmail(getApplicationContext(), getEmail);
PreferenceConfig.GetCoin(getApplicationContext(), getEmail);
PreferenceConfig.GetA256(getApplicationContext(), a256);
...
}
}
database.addValueEventListener(valueEventListener);
But i can`t understend how can i get data from db without hashmap
JSON file:
{
"User": {
"mail#gmail:com": {
"-NHTVinbEVUAqJwK8Umt": {
"getEmail": "mail#gmail.com",
"coins": 100,
.....
},
"-NHTVinpCPOJ4UPZvgpN": {
"a256":0,
"a257":0
...............
}
}
}
}
You won't be able to read the data under fields that are dynamically created:
{
"User": {
"mail#gmail:com": {
"-NHTVinbEVUAqJwK8Umt": {
"getEmail": "mail#gmail.com",
"coins": 100,
},
"-NHTVinpCPOJ4UPZvgpN": {
"a256":0, //👈
"a257":0 //👈
}
}
}
}
You'll be able to read all the data if your second child will have the same fields as the first one:
{
"User": {
"mail#gmail:com": {
"-NHTVinbEVUAqJwK8Umt": {
"getEmail": "mail#gmail.com",
"coins": 100,
},
"-NHTVinpCPOJ4UPZvgpN": {
"getEmail": "other#gmail.com", //👈
"coins": 200, //👈
}
}
}
}
Now, to read the data from such a structure, you have to create a reference that points to mail#gmail:com node and make a get() call as you can see in the following lines of code:
DatabaseReference db = FirebaseDatabase.getInstance().getReference();
DatabaseReference emailRef = db.child("User").child("mail#gmail:com");
emailRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
for (DataSnapshot ds : task.getResult().getChildren()) {
String email = ds.child("getEmail").getValue(String.class);
Log.d("TAG", email);
}
} else {
Log.d("TAG", task.getException().getMessage()); //Never ignore potential errors!
}
}
});
The result in the logcat will be:
mail#gmail.com
other#gmail.com
Or you can map each DataSnapshot object into an object of type User:
User user = ds.getValue(User.class);
This operation will work, only if your User class contains two fields called getEmail and coins. The first being a string and the second one a number.

How to do Arithmetic operations between two nodes of Firebase Realtime Database in Android Studio

I am having two tables Customers and Transaction nodes. Transaction node is related to data of Customer node by Vehicle Number a data in Customer node. I want to subtract the amount paid from the Customer node Due Amount
Customer Table:-
"Customers": {
"-NFFTcWFGLXi063jCTcT": {
"branch": "Rajeev Nagar",
"currentDownPayment": "80000",
"currentdueAmount": "20000.0",
"customerAadharNumber": "123456",
"customerAddress": "ANYWHERE",
"customerName": "VIKASH",
"customerPhoneNumber": "7481900892",
"customerTenure": "12",
"dateOfdelevry": "28/10/2022",
"downPayment": "100000",
"duePayment": "100000.0",
"emiPerMonth": "8333",
"emiStartDate": "26/10/2022",
"granterName": "RATHI",
"granterPhoneNumber": "7481900896",
"localitymodal": "NEAR ME",
"motorNumber": "QWERT",
"outStandingAmount": "120000.0",
"vehicleAmount": "200000",
"vehicleBodyType": "Steel",
"vehicleColour": "Gray",
"vehicleNumber": "1234567890QWERTYU"
},
Transection table:-
Transaction": {
"1234567890QWERTYU": {
"-NFFZLr7-9sTrZ1OlbjF": {
"dateOfPayment": "27/10/2022",
"discountGiven": "00",
"discountRemarks": "8000",
"lateFine": "no discount ",
"paymentReceived": "500"
}
The key of the Transaction Table is the same as the Customer Table Vehicle Number see the last data of the Customer Table
databasePaymentUpdate = FirebaseDatabase.getInstance().getReference("Customers");
databasePaymentUpdate.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists()) {
for (DataSnapshot ds : snapshot.getChildren()) {
String VehicleNumber = ds.child("vehicleNumber").getValue(String.class);
String vehNo = PaymentUpdateVehicleNumber.getText().toString().trim();
if (VehicleNumber.equals(vehNo)) {
Toast.makeText(PaymentUpdate.this, "Welcome to Jyoti Motors", Toast.LENGTH_SHORT).show();
}
To solve this problem, you have to use nested listener, as you can see in the following lines of code:
DatabaseReference db = FirebaseDatabase.getInstance().getReference();
DatabaseReference customersRef = db.child("Customers");
customersRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> customersTask) {
if (customersTask.isSuccessful()) {
for (DataSnapshot customerSnapshot : customersTask.getResult().getChildren()) {
String vehicleNumber = customerSnapshot.child("vehicleNumber").getValue(String.class);
DatabaseReference vehicleNumberRef = db.child("Transaction").child(vehicleNumber);
vehicleNumberRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> vehicleNumberTask) {
if (vehicleNumberTask.isSuccessful()) {
long sum = 0;
for (DataSnapshot paymentSnapshot : vehicleNumberTask.getResult().getChildren()) {
String paymentReceived = paymentSnapshot.child("paymentReceived").getValue(String.class);
sum += Integer.valueOf(paymentReceived)
}
Log.d("TAG", "sum: " + sum);
} else {
Log.d("TAG", task.getException().getMessage()); //Never ignore potential errors!
}
}
});
}
} else {
Log.d("TAG", task.getException().getMessage()); //Never ignore potential errors!
}
}
});
And the result in the logcat will be:
sum: 500
Please also note, that is recommended to store the prices as numbers and not as strings, case in which the above addition should look like this:
long paymentReceived = paymentSnapshot.child("paymentReceived").getValue(Long.class);
sum += paymentReceived;

why is it redirecting to the page which is suppose to happen in else clause even when the if statement is true(i feel)

So in my database, I have 2 nodes Customer and Driver. And I tried to make the login page in such a way that if the user is in the driver node he goes to the page meant for driver and the same way for the customer. My problem is even when it is Driver it is still going to the customer page.
#Override
public void onClick(View v) {
progressdialog.show();
auth.signInWithEmailAndPassword(binding.Email.getText().toString(),binding.Password.getText().toString())
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
progressdialog.dismiss();
if(task.isSuccessful()){
Toast.makeText(Login_Page.this, "Success", Toast.LENGTH_SHORT).show();
String uid = auth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference uidRef = rootRef.child("Driver");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if(snapshot.exists()) {
Toast.makeText(Login_Page.this,"LoginDriver",Toast.LENGTH_SHORT);
Intent intent=new Intent(Login_Page.this, HomePage.class);
startActivity(intent);
}
else {
startActivity(new Intent(Login_Page.this, Custhomepage.class));
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
};
uidRef.addListenerForSingleValueEvent(valueEventListener);
}
In this code, When the child is Driver it is supposed to go to the home page but instead, it goes to custhomepage even when the node is in Driver.
This is the database values:
{
"Users" : {
"Customer" : {
"5JEgU9isvdWFop4yt0lGFt9iSEo1" : {
"mail" : "Ashh#bbyshark.com",
"password" : "AlexXalexa",
"username" : "Ashhh"
},
"VyxUiy60khMEr4LPsNiKRTIxRs72" : {
"mail" : "xxx#g.com",
"password" : "yvuuuuuu",
"username" : "xxx"
},
"aRmz8jnue1NeDeGA08ey9H4rvIJ3" : {
"mail" : "aa#gmail.co.cin",
"password" : "123344555",
"username" : "aa"
},
"kgG9GBSK6xVdQUdTKEAnuU3OROv1" : {
"mail" : "tttt#class.com",
"password" : "---------------",
"username" : "j need"
},
"pWnRecYxRlQMwUJH5bZ10My5cBi1" : {
"mail" : "Ashh#babyshark.com",
"password" : "AlexXalexa",
"username" : "Ashhh"
},
"qHctsriB2GZYzQ2NULw0PmBdCkV2" : {
"mail" : "arfan#gmail.com",
"password" : "123456yus",
"username" : "Arfan"
}
},
"Driver" : {
"ZMqeFvM4gTh2vjTVu31JQY2jz9x2" : {
"mail" : "aww#gmail.com",
"password" : "696969",
"username" : "aditya"
}
}
}
}
Looks like you're adding the ValueEventListener to the entire Driver node so it is seeing if a snapshot exists at "Users/Driver" which it does. Instead the ValueEventListener should be attached to the child node using the UID to check if a snapshot exists at "Users/Driver/{UID}".
Changing this line:
DatabaseReference uidRef = rootRef.child("Driver");
To this:
DatabaseReference uidRef = rootRef.child("Users").child("Driver").child(uid);
Should solve the issue.

Cannot get reference to my auto generated push IDs in android

I am making an android app through android studio in java language. I have linked it to firebase Realtime database. There are auto generated push IDs as the last child. I want to retrieve my database values back in an activity. I am facing problem in giving reference to the push IDs.
This is what I have tried.
myRef = myfire.getReference().child("Data").child(strUID).child("Traffic").child("Wedding");
final String uid =myRef.getKey();
myRef.child(uid).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue() == null) {
Toast.makeText(getApplicationContext(),"Data Not Available",Toast.LENGTH_LONG).show();
} else {
String stData1 = (Objects.requireNonNull(dataSnapshot.child("stData1").getValue())).toString();
String stData2 = (Objects.requireNonNull(dataSnapshot.child("stData2").getValue())).toString();
String stData3 = (Objects.requireNonNull(dataSnapshot.child("stData3").getValue())).toString();
String stData4 = (Objects.requireNonNull(dataSnapshot.child("stData4").getValue())).toString();
category basic = new category(stData1,stData2,stData3,stData4);
tvBalance.setText(stData4);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
Please provide a practical example.
Edit
This is my database structure:------------
Data>>
user id>>>>
Traffic>>>>
Wedding>>>>
Auto ID>>>
>stData1
>stData2
>stData3
>stData4 //I want to get this last value//
my json file
{
"Data" : {
"UyhzVqsz1BVFKoePa2NEmlPFu382" : {
"Traffic" : {
"Wedding" : {
"-MYKeSN8GZ8WbI-8TfVB" : {
"stData1" : "15 Apr 2021,06:43:00:pm",
"stData2" : "Wedding",
"stData3" : "kkk",
"stData4" : "100"
}
}
}
}
}
}
The only ways to get a node is by either knowing its full path, or by knowing the path to the parent node, and then some unique value under the node. Neither seems to be the case for the stData4 in your JSON, so you'll have to load the entire Wedding node and then loop over the results to get the part you want.
This isn't too bad though:
myRef = myfire.getReference("Data").child(strUID).child("Traffic/Wedding");
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (!dataSnapshot.exists()) {
Toast.makeText(getApplicationContext(),"Data Not Available",Toast.LENGTH_LONG).show();
} else {
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
String stData1 = childSnapshot.child("stData1").getValue(String.class);
String stData2 = childSnapshot.child("stData2").getValue(String.class);
String stData3 = childSnapshot.child("stData3").getValue(String.class);
String stData4 = childSnapshot.child("stData4").getValue(String.class);
}
category basic = new category(stData1,stData2,stData3,stData4);
tvBalance.setText(stData4);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
The code above assumes that:
strUID has the value UyhzVqsz1BVFKoePa2NEmlPFu382

how to load data from firebase into arraylist in java

I have this piece of code in swift which loads up data from Firebase into dictionary a dictionary object.
i need to do same in java but its not dont know how. pl
// This is swift version
var yourArray = NSMutableArray()
func GetData() {
ref = Database.database().reference()
ref.child(bookTitle).observe(.value, with: { (snapshot) in
let children = snapshot.children
let allObj = children.allObjects
for i in 0 ..< allObj.count {
self.yourArray.add(allObj[i])
}
}) { (error) in
print(error)
}
Try This One
List<MyPojoClass> myList = new ArrayList<>();
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
myList.clear();
for (DataSnapshot postSnapshot: snapshot.getChildren()) {
MyPojoClass pojo= postSnapshot.getValue(MyPojoClass.class);
myList.add(pojo);
// here you can access others property of pojo class.
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("The read failed: " + firebaseError.getMessage());
}
});

Categories