How to update the status as true:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference applicationsRef = rootRef.collection("Root");
DocumentReference applicationIdRef = applicationsRef.document("Registration");
applicationIdRef.update("Status",true).addOnCompleteListener(task -> {
}).addOnFailureListener(new OnFailureListener() {
#Override public void onFailure(#NonNull Exception e) {
Log.d("TAG", "onFailure: "+e);
}
});
I was doing by this approach, but I was not getting how to go till status field .
The Map field is (quite deeply) nested. To update nested fields, you use dot notation like this:
applicationIdRef.update("Map1.Map2.Map3.Status",true)
Also see the Firebase documentation on updating nested fields
But even then, since the value is in an array, there's no way update a single item in an array by its index. So Map1.Map2.Map3.0.Status won't work. You will need to:
Read the document from the database in your application code.
Update the item in the array in the nested field.
Write the entire array back to the database.
This updating a single item in an array has been covered extensively before, so I recommend checking out some of those answers too.
Related
How can I program a key in my FirebaseDatabase that is created by the userName. wText should then be the text: "" Value.
I try to create a key but when i run my app it removes all values in my database
The Code:
`
// getting text from our edittext fields.
String nameValue = userName.getText().toString();
String textValue = wText.getText().toString();
// below line is for checking whether the
// edittext fields are empty or not.
if (nameValue.isEmpty() && textValue.isEmpty()) {
// if the text fields are empty
// then show the below message.
Toast.makeText(AddTextActivity.this, "Please add some data.", Toast.LENGTH_SHORT).show();
return;
} else {
// else call the method to add
// data to our database.
addDatatoFirebase(nameValue, textValue);
finish();
}
}
});
}
private void addDatatoFirebase(String name, String wText) {
// below 3 lines of code is used to set
// data in our object class.
Messages.setuserName(name);
Messages.setText(wText);
// we are use add value event listener method
// which is called with database reference.
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
// inside the method of on Data change we are setting
// our object class to our database reference.
// data base reference will sends data to firebase.
myRef.setValue(text);
// after adding this data we are showing toast message.
Toast.makeText(AddTextActivity.this, "data added", Toast.LENGTH_SHORT).show();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
// if the data is not added or it is cancelled then
// we are displaying a failure toast message.
Toast.makeText(AddTextActivity.this, "Fail to add data" + error, Toast.LENGTH_SHORT).show();
}
}); `
It seems you might be using set() function to update data in firebase.
( in your case setValue(), I'm not sure if it is Firebase function or user defined function , Firebase uses set() method in almost in every SDK, not sure about Java SDK for Firebase )
Please note that set() will replace the existing value, or create a new key if there isn't any.
Use update() function instead of set()
Ways to Save Data
set - Write or replace data to a defined path, like messages/users/
update - Update some of the keys for a defined path without replacing all of the data
push - Add to a list of data in the database. Every time you push a new node onto a list, your database generates a unique key, like
messages/users//
transaction - Use transactions when working with complex data that could be corrupted by concurrent updates
refer the docs here
Here are the various attributes of a person.
I want to implement a search where the results come if any of the fields: specializationField, hospitalName or fullName have the same letters.
For example if I search 'sh', this person should appear in the field, because of the similar hospital name.
This is the code I am using to search only for fullName:
FirebaseRecyclerOptions<DoctorHelperClass> options =
new FirebaseRecyclerOptions.Builder<DoctorHelperClass>()
.setQuery(FirebaseDatabase.getInstance().getReference().child("Doctor").orderByChild("fullName").startAt(s.toUpperCase()).endAt(s.toLowerCase()+"\uf8ff"), DoctorHelperClass.class)
.build();
adapter = new DoctorsAdapters(options, FindDoctorActivity.this);
adapter.startListening();
binding.rvListDoctors.setAdapter(adapter);
Please help me out
As #Puf said, you can't achieve it at Firebase Realtime Database but you can do it at client side which mean at the Android part.
First, you cannot use FirebaseUI which is you are currently using, instead you need to use https://firebase.google.com/docs/database/android/read-and-write#read_data
ValueEventListener postListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// You have to make for each loop
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
DoctorHelperClass doc = snapshot.getValue(DoctorHelperClass.class);
//List them in an array
docList.add(doc);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
}
};
mPostReference.addValueEventListener(postListener);
Once you have added all the list of doctors. You can compare them using the arrayList.
You can do something like this.
private void searchDoc(final String inputDoc){
boolean isFound = false;
for (DoctorHelperClass doc in docList){
if (doc.getFullName() == inputDoc && doc.getHospitalName() == inputDoc){
isFound = true;
//Do something if found
}
}
}
I hope you get the concept of it.
There is no support for OR conditions in Firebase Realtime Database. You will either have to perform multiple queries and merge the results client-side, or create a specialized field for performing this search.
But given your question, you may be looking for text search capabilities that are well beyond what Firebase Realtime Database handles. Instead of trying to shoehorn those requirements onto Firebase, I recommend using an additional (or even other) database for meeting your text search requirements.
Also see:
Use firebase realtime database create search function
How to search anywhere in string in Firebase Database - Android
Searching in Firebase without server side code
Firebase and indexing/search
I am working on an app for a hotel, which enables hotel management to report and view concerns and issues. I am using Android and Firebase for this app.
Here is the database structure of a reported concern:
To minimize data download and optimize speed, I am adding "Active" and "Resolved" nodes in the database, like below:
Now, the hotel wants me to add the function to create an Excel report of concerns closed/resolved within the past month. For this, I will be attaching a Single Value Event Listener on the "resolved" node, get keys of resolved concerns, then for each key, fetch data from "allConcerns" node, store each node's data into an ArrayList of String. After which I will use this JSON to Excel API for Android to create Excel file.
I am able to access keys of resolved concerns with this code:
DatabaseReference resolvedReference = FirebaseDatabase.getInstance().getReference()
.child(getApplicationContext().getResources().getString(R.string.concerns))
.child(getApplicationContext().getResources().getString(R.string.resolved));
final ArrayList<String> keys = new ArrayList<>();
resolvedReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
//Getting keys of all resolved concerns in keys arraylist here
for (DataSnapshot ds : snapshot.getChildren()){
keys.add(ds.getValue(String.class));
}
//Storing JSON data in this arraylist
final ArrayList<String> data = new ArrayList<>();
for(int i = 0; i<keys.size() ; ++i){
String key = keys.get(i);
//Getting data of each concern here
FirebaseDatabase.getInstance().getReference().child(getApplicationContext().getResources().getString(R.string.allConcerns))
.child(key).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
String type = snapshot.child("type").getValue().toString();
Log.i("Type", type);
if(type.equals("0")) {
SafetyConcernClass s = snapshot.getValue(SafetyConcernClass.class);
Log.i("Snapshot of key", s.toString());
data.add(s.toString());
}
else{
GembaWalkClass g = snapshot.getValue(GembaWalkClass.class);
Log.i("Snapshot of key", g.toString());
data.add(g.toString());
}
Proof proof = snapshot.child("proof").getValue(Proof.class);
Log.i("Proof", proof.toString());
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
//Issue I am facing is here
Log.i("Data size", String.valueOf(data.size()));
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
The real issue here is while logging data.size(). Since Firebase is asynchronous, FOR loop ends before data is fetched and entered into the data ArrayList, hence it gives me a size of 0. And since no data is fetched, I can't create an Excel file.
My question is, how can I make sure I am proceeding to log data.size() ONLY after data of respective resolved concerns is stored in the ArrayList?
The typical approach is to keep a counter or a countdown latch to track how many of the concern snapshots you've already downloaded. Once the counter reaches keys.size() you know that you're done.
Also see Setting Singleton property value in Firebase Listener
You should write your method
addListenerForSingleValueEvent
using AsyncTask or Kotlin coroutines
and in onPostExecute() of AsyncTask, you can proceed to further action.
I received the user's email and designated it as the name of the document,
and stored the user information in the document in an array. I tried running my code, but only the Toast message is executed, not deleted.
I have listed the arrays as a list using RecyclerView. Deletion will be implemented through showPop() method.
This is my Firestore database enter image description here
I want to delete index-0
private void showPopup(View v,final int position) {
PopupMenu popup = new PopupMenu(activity, v);
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener(){
#Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()) {
.....
case R.id.delete: //delete
final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
final FirebaseFirestore db = FirebaseFirestore.getInstance();
final Map<String, Object> updates = new HashMap<>();
updates.put(user.getEmail(),FieldValue.delete());
//db.collection("medicinday").document(mDataset.get(position).getId())
// .delete()
db.collection("medicinday").document(user.getEmail()).update("add_day", FieldValue.arrayRemove(user.getEmail()))
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(....
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
....
There is no way you can delete/update an element at a specific index in a Firestore array. For more info, please check my answer from the following post:
Is there any way to update a specific index from the array in Firestore
In your particular case, the add_day property is an array that holds objects. If you want to remove an item from that array, you need to pass the entire object value of the item. It will not work if you just pass an index or one of the nested values in that item.
For your type of data, you'll need to build a Map with the exact content of your first item and pass that object to the update() method, like in the following lines of code:
String email = FirebaseAuth.getInstance().getCurrentUser().getEmail();
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference medicinDayRef = rootRef.collection("medicinday");
DocumentReference emailRef = medicinDayRef.document(email);
HashMap<String, Object> doc = new HashMap<>();
doc.put("day", "monday");
doc.put("king" , "A");
doc.put("nam" , "ren");
doc.put("time1" , "AM 7:30");
doc.put("time2" , "PM 2:30");
doc.put("time3" , "PM 8:30");
emailRef.update("add_day", FieldValue.arrayRemove(doc));
Be aware that if you don't know the entire item's contents, it will not work.
Another option might be to read the document, modify the list on the client by removing the item at the position one, write it modified list back to the document, and in the end simply write it back to Firestore.
More info about this topic can be found here:
Android Firestore querying particular value in Array of Objects
And in the following article:
How to map an array of objects from Cloud Firestore to a List of objects?
It seems like your line to delete from your Firestore is commented out, unless that is intentional for now.
From the picture you have sent, I understand that add_day is your array and 0 is the element you would like to delete. You could do so by accessing your document's field add_day, then using arrayRemove() to specifically delete the element of your choice.
Roughly referring to the linked documentation, I believe you could achieve this by running the following.
DocumentReference doc = db.collection("medicinday").document("222#naver.com");
ApiFuture<WriteResult> remove = doc.update("add_day", FieldValue.arrayRemove("0"));
System.out.println("Update time : " + arrayRm.get());
I am building a chatroom application and am trying to query all messages then separate them accordingly based on the message sender.
This is what my Firestore architecture looks like:
And my code so far:
CollectionReference chatRoomMsgs = db.collection("chatrooms").document(chatRoomID).collection("Messages");
chatRoomMsgs.get()
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
for(QueryDocumentSnapshot documentSnapshot: queryDocumentSnapshots){
if(documentSnapshot.get("sentby") == firebaseUser.getUid()){
}
}
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
}
});
What I am (currently) trying to do is pull ALL chatroom messages first, and then separate them out in onSuccess.
I am trying to say "ok if the message was sent by this user, grab the image field value of that same document and add it to an array so the image can be accessed later, and if the message was not sent by the same user, also grab the image url but add it to a different array"
How can I do this? Thanks!
Update
I tried adding the while loop below to get some sort of output, wasn't triggering
ArrayList<String> sentPics = new ArrayList<String>();
while(documentSnapshot.get("sentby") == firebaseUser.getUid()){
sentPics.add(documentSnapshot.get("image").toString());
Log.d("PICLIST", sentPics.toString());
}
If you want to get all the messages sent by a specific user, then you should use the following query:
CollectionReference chatRoomMsgs = db.collection("chatrooms").document(chatRoomID).collection("Messages");
Query sendByQuery = chatRoomMsgs.whereEqualTo("sentby", firebaseUser.getUid());
sendByQuery.addOnSuccessListener(/* ... */);
Using this solution you'll significantly reduce the number of read operations as you get as a result only the messages that correspond to the logged-in user.
Your solution is very expensive because you are getting all messages that exist in the Messages collection and you filter them on the client. If you have a total of 100 messages in the collection but only 10 correspond to the logged-in user, you'll be charged with 100 reads. In my solution, you'll only be charged with 10, as the query only 10 messages returns.
If want to see another approach, here you can find a tutorial on how to create a complete and functional Firestore Chat App.
What you need to do is make a POJO named Message that maps to your Messages collection with member variables image and sentby and convert the documentSnapshot to a Message object using:
Message message = documentSnapshot.toObject(Message.class)
From there on, you can just use the getters to achieve what you want.
Hope it helps!