How can I implement if-else to check if the value of the money field is equal or greater (pre defined value in code) checking on the Realtime database money field? Only after this verification runs the code? I did a web search but all the methods I have searched but none were successful in the implementation.
ref.child("users").child(user.getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
DatabaseReference ref = FirebaseDatabase.getInstance().getReference()
.child("users").child(user.getUid()).child("money");
ref.runTransaction(new Transaction.Handler() {
#Override
public Transaction.Result doTransaction(MutableData mutableData) {
Object currentMoney = mutableData.getValue();
int totalMoney = 0;
if (currentMoney == null) {
totalMoney = moneyToRemove;
} else {
totalMoney = Integer.parseInt(String.valueOf(currentMoney)) - moneyToRemove;
}
mutableData.setValue(totalMoney);
return Transaction.success(mutableData);
}
#Override
public void onComplete(DatabaseError databaseError, boolean b,
DataSnapshot dataSnapshot) {
// Transaction completed
}
});
Db structure
To get all users that have the value of money property greater than or equal to 7 for example, you should definitely use a query that looks like this:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference usersRef = rootRef.child("users");
Query moneyQuery = usersRef.orderByChild("money").startAt(7);
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
ds.child("money").getRef().setValue(ServerValue.increment(money));
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d("TAG", databaseError.getMessage()); //Don't ignore potential errors!
}
};
moneyQuery.addListenerForSingleValueEvent(valueEventListener);
However, if you only want to do this operation only on the logged-in user, please use the following lines of code:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference uidRef = rootRef.child("users").child(uid);
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(ds.child("money").getValue(Long.class) >= 7)) {
dataSnapshot.child("money").getRef().setValue(ServerValue.increment(money));
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d("TAG", databaseError.getMessage()); //Don't ignore potential errors!
}
};
uidRef.addListenerForSingleValueEvent(valueEventListener);
In which the money variable can be any positive number for an increment operation or a negative number for a decrement operation. Besides that, there is no need to run a transaction for a simple increment/decrement operation. We can simply use the simpler newly added ServerValue.increment(value) option. The transactions are used only when we need to read the value of the property first.
Both solutions will work, only if you change the type of your money property in the database from String to number. So please do the following change:
money: "7" //See the quotations marks?
To:
money: 7 //No quotations marks
Related
What I really need is to show every value in the "Income" field in TextView.
250
105
Is this possible? If it is possible please help me.
This is how I insert values to database
private void addReport() {
Float total_Income = Float.valueOf(tv_total_income.getText().toString());
String current_date = tv_current_date.getText().toString();
SimpleDateFormat sdf = new SimpleDateFormat("MMMM");
String currentDateandTime = sdf.format(new Date());
FirebaseDatabase mDatabase = FirebaseDatabase.getInstance();
DatabaseReference mDbRef = mDatabase.getReference("Reports"+"/"+currentDateandTime+"/"+current_date).child("Date");
mDbRef.setValue(current_date);
DatabaseReference mDbRef1 = mDatabase.getReference("Reports"+"/"+currentDateandTime+"/"+current_date).child("Income");
mDbRef1.setValue(total_Income);
}
While Sairaj Sawant's answer might work, keep in mind that there is no need to attach a listener at every iteration of the loop. A more convenient solution is to attach a listener only once, like in the following lines of code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference juneRef = rootRef.child("Reports").child("June");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String totalIncome = "";
for(DataSnapshot ds : dataSnapshot.getChildren()) {
totalIncome = totalIncome + ds.child("Income").getValue(String.class) + " ";
}
Log.d("TAG", totalIncome);
textView.setText(totalIncome);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d("TAG", databaseError.getMessage()); //Don't ignore errors!
}
};
juneRef.addListenerForSingleValueEvent(valueEventListener);
This code will work only if the Income property is of type String, as it is set in your 20-06-2020 child. However, the above code will not work if the value is set as an Integer as it set in your second 21-06-2020 child. Remember, both types of values must match. You either set both as String and the above code will work, or you set them as numbers, case in which you should use this line:
totalIncome = totalIncome + ds.child("Income").getValue(Long.class) + " ";
Try accessing the children of June under Reports and looping through to get income as below :
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference reportsRef = rootRef.child("Reports").child("June");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
String key = ds.getKey();
DatabaseReference keyRef = rootRef.child(key).child("income");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot ds1 : dataSnapshot.getChildren()) {
String income = ds1.getValue(String.class);
Log.d("TAG", income);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
keyRef.addListenerForSingleValueEvent(valueEventListener);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
reportsRef.addListenerForSingleValueEvent(eventListener);
Everything is working fine, I think just userDataModel.setUserRating(aFloat / (int) dataSnapshot.getChildrenCount()); is not giving value.
And String.valueof(aFloat / (int) dataSnapshot.getChildrenCount()));
Is also giving the correct value.
FirebaseDatabase.getInstance().getReference().child("Users").child(userDataModel.getUserID()).child("Ratings")
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
userDataModel1 = dataSnapshot.getValue(UserDataModel.class);
aFloat = aFloat + Float.parseFloat(Objects.requireNonNull(dataSnapshot1.getValue()).toString());
}
userDataModel.setUserRating(aFloat / (int) dataSnapshot.getChildrenCount());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
UserDataModel
public class UserDataModel {
float userRating;
public float getUserRating() {
return userRating;
}
public void setUserRating(float userRating) {
this.userRating = userRating;
}
}
Image URL: https://i.stack.imgur.com/t14Cc.png
This is happening maybe because userDataModel.setUserRating(aFloat / (int) dataSnapshot.getChildrenCount()); is returning null so you don't get a value
The problem in your code us the fact that your UserDataModel has a field named userRating, while in your database the property is actually a uid. This property is dynamic, so you cannot use a POJO class for that. If you want to get the values of those ratings, please try this:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference ratingsRef = rootRef.child("Users").child(uid).child("Ratings");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
double rating = ds.getValue(Double.class);
Log.d("TAG", "rating: " + rating);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d("TAG", databaseError.getMessage()); //Don't ignore errors!
}
};
ratingsRef.addListenerForSingleValueEvent(valueEventListener);
The output in the logcat will be values of all ratings that exist within the Ratings node.
3.5
2
Now, you can simply make the average or whatever you need with those values.
I am trying to write a query to check if there is any "Pending" status on mcustDeliveryStatus. I want to check in Order node that is there any Pending status for mcustDeliveryStatus.
I wrote the following query
mDatabase = FirebaseDatabase.getInstance().getReference("Order");
final Query query = mDatabase.OrderByChild("mcustDeliveryStatus").equalTo("Pending");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
Toast.makeText(VWelcome.this, "new order", Toast.LENGTH_LONG).show();
Intent i = new Intent(VWelcome.this, ViewOrderRequest.class);
startActivity(i);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
This query works fine but the problem is intent runs even when there is no Pending status in my Order node. Anyone knows why?
Since you annotate your DataSnapshot object with #NonNull, it means that you tell the compiler that your object cannot be null, so it will always return something. With other words, if there are no results, it will return an empty DataSnapshot object. To solve this, you should check how many children are inside that object using the following lines of code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference orderRef = rootRef.child("Order");
Query query = orderRef.orderByChild("mcustDeliveryStatus").equalTo("Pending");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
long count = dataSnapshot.getChildrenCount();
if (count > 0) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String mGasBand = ds.child("mGasBand").getValue(String.class);
Log.d(TAG, mGasBand);
}
} else {
Log.d(TAG, "No data!");
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
}
};
query.addListenerForSingleValueEvent(valueEventListener);
I am trying to create child inside child -LoVaDPuBRr4K2JSkc_j , but how?
Code :
firebaseAuth = FirebaseAuth.getInstance();
firebaseDatabase = FirebaseDatabase.getInstance();
databaseDocument = firebaseDatabase.getReference(firebaseAuth.getUid()).child("Document");
To create a child in -LoVaDPuBRr4K2JSkc_j, you can do:
databaseDocument.child("-LoVaDPuBRr4K2JSkc_j").child("newProperty").setValue("new value");
If you want to generate a new child with an auto-generated key, it'd be:
databaseDocument.child("-LoVaDPuBRr4K2JSkc_j").push().setValue("new value");
Both of these assume that you know the -LoVaDPuBRr4K2JSkc_j value in your code. This is required to be a able to add a child, as writing to a location in the database requires that you know the full path to that location.
You'll not want to hardcode this key of course, so there are two common options to have the key:
Pass it along your app from the moment when you loaded the data.
Use some other value of the node that allows you to perform a query on the database to look up the key.
The simplest solution to add a new property inside your -LoVaDPuBRr4K2JSkc_j object would be use that pushed id in your reference like in the following lines of code:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = rootRef.child(uid).child("Document").child("-LoVaDPuBRr4K2JSkc_j");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
dataSnapshot.getRef().child("newProperty").setValue("newValue");
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
}
};
ref.addListenerForSingleValueEvent(valueEventListener);
Edit:
Accodring to your comment, if you have more than one key, then you should use a query. The following code will do the trick:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Query query = rootRef.child(uid).child("Document").orderByChild("inspectorName").equalTo("Test");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
ds.getRef().child("newProperty").setValue("newValue");
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
}
};
query.addListenerForSingleValueEvent(valueEventListener);
My code and its work :
firebaseAuth = FirebaseAuth.getInstance();
firebaseDatabase = FirebaseDatabase.getInstance();
databaseProduct = firebaseDatabase.getReference(firebaseAuth.getUid()).child("Document");
String id = databaseProduct.push().getKey();
final String productID = databaseProduct.child(id).child("Product").push().getKey();
final Items items = new Items(productID, dates, nameInspector, locate, product, priceProduct, amount, code);
databaseProduct.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot getDocumentKey : dataSnapshot.getChildren()) {
String getDocumentID = getDocumentKey.getKey();
String sameDocumentID = getDocumentKey.child("documentID").getValue().toString();
if (getDocumentID.contentEquals(sameDocumentID)) {
databaseProduct.child(getDocumentID).child("Product").child(productID).setValue(items);
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
I have the following database. What I need is to get the total count of comments per post when posting UID equal to current_user_uid.
Any suggestion on how to do this?
To solve this, please use the following code:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Query query = rootRef.child("Posts").orderByChild("uid").equalTo(current_user_uid);
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
long count = ds.child("comments").getChildrenCount();
Log.d("TAG", "Count: " + count);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage());
}
};
query.addListenerForSingleValueEvent(valueEventListener);