How to remove specific entries from Firebase in Android Studio? - java

I have the following structure in Firebase:
where the entries contain an image and a timestamp. The name of each entry is randomly generated and the timestamp is an int larger than 0.
What I want:
To delete the entries with a timestamp smaller than a specific value.
My current progress:
I should be able to retrieve the list of sorted entries with the following code:
Firebase myFirebaseRef = new Firebase("https://someURL.firebaseio.com/");
Firebase listOfObjects = myFirebaseRef.orderByChild("timestamp").getRef();
What's next:
I want to iterate through and/or somehow only remove specific entries in the listOfObjects. Possibly with some if-statements?

First I believe you could use endAt() to filter just the entries you need
Firebase listOfObjects = myFirebaseRef.orderByChild("timestamp").endAt(myLimit).getRef();
Then something like this should work
listOfObjects.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot querySnapshot) {
queurySnapshot.getRef().removeValue()
}
}

Related

is there any way to fetch records from firebase realtime database whose attribute has a value in my predefined list?

Basically what I am trying to do is I have a database with the name users having an attribute username. I have some usernames in one list and I want to show details of these users only whose username is present in the list. How can I write a query to fetch details of those users only whose username is found in this list? And note that there is no lexicographical ordering so i can't use startAt() and endAt() functions as well.
code snippet:
=> myList contains usernames. This code doesn't yield accurate results.
Any help would be really appreciated! Thank you!
FirebaseRecyclerOptions<MainModel> options =
new FirebaseRecyclerOptions.Builder<MainModel>()
.setQuery(FirebaseDatabase.getInstance().getReference().child("users").orderByChild("username")
.startAt(myList.get(0)).endAt(myList.get(myList.size()-1)),MainModel.class).build();
As already mentioned in the comment, the Firebase-UI library doesn't help in your case, because it doesn't allow you to pass multiple queries to the FirebaseRecyclerOptions object. So you need to perform a separate query and use the combined result.
When you are calling .get() on a Firebase Realtime Database query object, you are getting back a Task object. So the key to solving this problem is to use whenAllSuccess(Collection> tasks). In your case, it should look like this:
DatabaseReference db = FirebaseDatabase.getInstance().getReference();
DatabaseReference usersRef = db.child("users");
Query query = usersRef.orderByChild("username");
List<Task<DataSnapshot>> tasks = new ArrayList<>();
for (String username : myList) {
tasks.add(query.equalTo(username).get());
}
Tasks.whenAllSuccess(tasks).addOnSuccessListener(new OnSuccessListener<List<Object>>() {
#Override
public void onSuccess(List<Object> list) {
//Do what you need to do with your list.
for (Object object : list) {
MainModel mm = ((DataSnapshot) object).getValue(MainModel.class);
if(mm != null) {
Log.d("TAG", mm.getUsername());
}
}
}
});
Assuming that you have in your MainModel class a getter called getUsername(), the result in your logcat will be all the usernames of all returned children.

How can I write Arraylist data to Firebase Database in Java?

I have an android app with firebase as the backend. I have an activity where the use populates a list for a recycler view which they want to save to the database.
Below is a screenshot of the Firebase Realtime Database structure of my database:
The values of children in the Values node is what I'm using to create the id for new data that is added.
I have an arraylist of sales objects populated by the user which is to be saved in a new Sales node and would like to use the value in Values/Sales to populate the ids for each item in the arraylist.
Below is my code for saving that data. However in the database, only the last item in the arraylist is saved.
ArrayList<Inventory> salesArrayList = new ArrayList<>();
------------------- Code for populating data into the arraylist ----------------------
for (int i = 0; i < salesArrayList.size(); i++){
int finalI = i;
databaseReference.child("Values").child("Sales").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
String newCount = String.valueOf(Integer.parseInt(String.valueOf(snapshot.getValue()))+1); // Gets the original value saved and adds 1 to it to be used as the id in the 'Sales' node
DatabaseReference countReference = databaseReference.child("Sales").child(newCount);
countReference.child("date").setValue(currentDate);
countReference.child("name").setValue(salesArrayList.get(finalI).getName());
countReference.child("quantity").setValue(salesArrayList.get(finalI).getQuantity());
countReference.child("unit_price").setValue(salesArrayList.get(finalI).getValue()/salesArrayList.get(finalI).getQuantity());
countReference.child("value").setValue(salesArrayList.get(finalI).getValue());
databaseReference.child("Values").child("Sales").setValue(Integer.parseInt(newCount)); // Updates the number of sales
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
If there are 7 items in the arraylist, I'd like a way to have all them saved in the Sales similar to the Purchases node rather than only the last item on the arraylist.
This doesn't work (and I'm surprised it even compiles):
databaseReference.child("Values").child("Sales")(Integer.parseInt(newCount)); // Updates the number of sales
To write back the incremented number of sales:
snapshot.getReference().setValue(snapshot.getValue(Long.class)+1);
Note that in general using such sequential numeric keys in Firebase is an anti-pattern. I highly recommend using Firebase's native push() keys, which are also always incrementing but provide much stronger guarantees outside of that. To read more about that, check out: Best Practices: Arrays in Firebase.
I can't comment, but I can answer, but I don't know if my answer will be correct.
If you are only updating the last item on the array it would seem to me that you are at each iteration overwriting the same object and finally saving only that object to the database.
Is there an append method? Or does the documentation say anything about this?
This for me seems the most probable cause.
Maybe you each time need a new instance of the 'databaseReference'-object.

How to get a value of Firebase by index?

I am trying to retrieve data from Firebase depending on the position. If I don't know, what the key of the first value is like, how am I able to access the value of the first position?
ticketCodes.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
GenericTypeIndicator<List<String>> t = new GenericTypeIndicator<List<String>>() {};
List<String> yourStringArray = dataSnapshot.getValue(t);
// Here I want to receive the value of the first index in firebase without knowing what the key is.
//I am not able to. Though if I put "get(firstKey)" it gives me the value of the first index.
String value = yourStringArray.get(0);
Is there another way of how to get access of the first position in this List?
My database looks like the following:

firebase check if child exists

So I have my backend using firebase. What I'm aiming to do is to add user matches to a user id. However, when the user initially signs up, they have no matches. What I'm trying to do is to check whether or not the "match" child exists within a user child, if not a list child is created and the first match is stored. However, if it already exists, the match is simply added. Here's my code:
public void setMatch(final String match){
final Firebase ref = new Firebase("FIREBASEURL");
final Firebase userRef = ref.child("Flights").child(userName);
userRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
System.out.println("does the child exist? " + dataSnapshot.child("matches").exists());
if(!dataSnapshot.child("matches").exists()){
ArrayList<String> matches = new ArrayList<String>();
matches.add(match);
Firebase matchesRef = userRef.child("matches");
matchesRef.setValue(matches);
userRef.removeEventListener(this);
}else if(dataSnapshot.child("matches").exists()){
Map<String, Object> matches = new HashMap<>();
matches.put("matches", match);
userRef.child("matches").push().setValue(matches);
userRef.removeEventListener(this);
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
Currently, the value is being added twice (the else if is called twice if the field already exists/its called if it doesn't). I'm not sure what I'm doing wrong.
This sounds pretty overcomplicated. In the Firebase Database, it's often best to separate read and write operations as much as possible. And while push ids are a great way to store data in a chronological way; if items have a natural key, it is often better to store them under that key.
For example if your String match is really a String matchId, you can ensure that each match is present at most once by using matchId as the key.
userRef.child("matches").child(matchId).setValue(true);
This operation is idempotent: it will give the same result no matter how often you run it.
You'll note that I don't check of matches already exists: the Firebase Database automatically creates all nodes that are needed to store the value and it automatically removes all nodes that have no values under them.
It looks like you create the field if it doesn't exist in the if block, and then test to see if that field (which was just created) exists, and it now does, so it adds it again. The removeEventListener call will remove the listener, but will not stop the current code from completing.
Try:
if(!dataSnapshot.child("matches").exists()){
ArrayList<String> matches = new ArrayList<String>();
matches.add(match);
Firebase matchesRef = userRef.child("matches");
matchesRef.setValue(matches);
userRef.removeEventListener(this);
return;
}else if(dataSnapshot.child("matches").exists()){
Map<String, Object> matches = new HashMap<>();
matches.put("matches", match);
userRef.child("matches").push().setValue(matches);
userRef.removeEventListener(this);
}
Adding the return statement should quite the current call, and still disable the Listener as you intended.

ParseQuery: convert from list of prices in database to strings android

​Hi All,
I am trying to build a scrolling custom listview that displays a list of products ordered by Price ascending. However I just realized I was storing the prices as strings which means $1000.00 comes before $2.01 because it is a character and not a number. I have converted my data to a "Number" on Parse and believe the best type to retrieve it is a double (can anyone comment on that for dollar amounts). The problem is I need to keep it as a number convert it to a string and then pass it to the listview for display on a text field. Initially i had
PPI.setProductprice((String) product.get("Price"));
like this:
// Locate the class table named "Products" in Parse.com
ParseQuery<ParseObject> query = new ParseQuery<ParseObject>(
"Products");
// Locate the column named "Price" in Parse.com and order list
// by ascending
query.orderByAscending("Price");
ob = query.find();
for (ParseObject product : ob) {
// Locate images in PrimaryPhoto column
ParseFile productimage = (ParseFile) product.get("PrimaryPhoto");
ProductPopulation PPI = new ProductPopulation();
PPI.setProductname((String) product.get("Name"));
PPI.setProductbrand((String) product.get("Brand"));
PPI.setProductprice((String) product.get("Price"));
PPI.setProductimage(productimage.getUrl());
productpopulationlist.add(PPI);
I then tried putting it into an array of doubles an iterating through it to convert to strings.
My last attempt which probably doesn't make sense was to change it like this:
PPI.setProductprice((Double) product.getDouble("Price"));
I am fairly knew to Android and any help you can give me would be appreciated.
Thanks in advance.
OK so i do not get the context here but what you can do is save the price as a string and when extracting it you could call Integer.parseInt(String intvalue); on the string to convert the value back to int then you can do all operations you ought to do. you can get a disordered array from the server and arrange it at device level that will save you some time and logic.
I don't know what is the ProductPopulation class you use to populate the list, so I can not say what exactly is the best way in your case, but in general a list can be ordered by means of the Collections.sort() method (see the method documentation).
You could sort the list before you add it to your list view. To sort a list the way you need, you must provide a comparator, than obtains the required values (fields or method results) from the objects that comprise your list, compares the obtained values and returns -1, 0, or 1, depending on the comparison result.
It could look somewhat like this:
for (...) {
ItemClass newObject = new ItemClass(); // new list item
// ...here add the values to the list item...
theList.add(newObject); // add the new item to the list
}
// now sort the list before adding it to the list viewer
Collections.sort(theList, new Comparator<ItemClass>() {
#Override
public int compare(ItemClass o1, ItemClass o2) {
// obtain and compare the values you need
return Double.compare(o1.getDouble(), o1.getDouble());
// you could also do something like
// Double.compare(
// Double.parseDouble(o1.getString()),
// Double.parseDouble(o2.getString()));
// but it would be much slower
}
});
// now add the sorted list to the viewer
listViewer.setList(theList);

Categories