I have Firebase node that look like this
How can i make a condition if (name.equalsTo("someValue") to scan database inside campus and get reference to node with key? I this case, i want to get reference or key of kazjap
To find the node under /campus/building where name has a certain value, you can use a query like this:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("campus/building");
Query query = ref.orderByChild("name").equalTo("someValue");
And then read the results of the query with:
query.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (!task.isSuccessful()) {
Log.e("firebase", "Error getting data", task.getException());
}
else {
for (DataSnapshot childSnapshot: task.getResult().getChildren()) {
Log.d("firebase", String.valueOf(childSnapshot.getKey()));
}
}
}
});
Or:
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
// Handle the data
Log.d("TAG", childSnapshot.getKey())
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting User failed, log a message
Log.w("firebase", "Error getting data", databaseError.toException());
// ...
}
});
Firebase queries only work on direct child nodes, so this only works if you know the /campus/building part of the path already. There is no way to search across the entire campus for a building by its name in any campus. For more on that, see Firebase Query Double Nested
Related
I am working on an application where I have saved my data in firebase Firestore in nested collection now when I am trying to get/retrieve the data from Firestore but not able to get it. please guide me where am I wrong??
CODE TO WRITE/ADD THE DATA IN FIRESTORE
DocumentReference uidRef = firebaseFirestore.collection("listing_details").document(uid);
uidRef.collection("room_details").add(user).addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
#Override
public void onSuccess(DocumentReference documentReference) {
Toast.makeText(getContext(), "data added", Toast.LENGTH_SHORT).show();
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(getContext(), "data adding failure", Toast.LENGTH_SHORT).show();
}
});
CODE FOR DATA RETRIEVING
db.collection("listing_details").document().collection("room_details").get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
List<DocumentSnapshot> list = queryDocumentSnapshots.getDocuments();
for (DocumentSnapshot d : list)
{
RoomsDetails obj = d.toObject(RoomsDetails.class);
roomsDetails.add(obj);
}
roomsAdapter.notifyDataSetChanged();
}
});
DATA RETRIEVING CODE (UPDATED)
roomDetailsRef.document(doc_id).get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
//GUIDE ME HERE HOW CAN I ITERATE THROUGH IT SIR PLEASE
}
});
Each time you're calling .document() to create the following reference, without passing anything as an argument:
db.collection("listing_details").document().collection("room_details")
// 👆
It means that you're generating a brand new unique document ID. If you want to create a reference that points to a particular document, then you have to pass the particular document ID that already exists in the database to the document() method, and not generate a new one.
So your code should look like this:
//Code to add data to Firestore.
FirebaseFirestore db = FirebaseFirestore.getInstance();
DocumentReference uidRef = db.collection("listing_details").document(uid);
CollectionReference roomDetailsRef = uidRef.collection("room_details");
String docId = roomDetailsRef.document().getId();
roomDetailsRef.document(docId).set(user).addOnSuccessListener(/*.../*);
// 👆
See, I have used DocumentReference#getId() to get the ID of the document, and DocumentReference#set(Object data) to actually add the document to Firestore.
//Code to read data from Firestore.
roomDetailsRef.document(docId).get().addOnSuccessListener(/*.../*);
// 👆
See, I have passed the document ID that was generated earlier, to the CollectionReference#document() method.
Edit:
If you want to get all documents that exist under the room_details collection, then please use the following lines of code:
roomDetailsRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
if (document != null) {
RoomsDetails obj = document.toObject(RoomsDetails.class);
roomsDetails.add(obj);
}
}
roomsAdapter.notifyDataSetChanged();
} else {
Log.d(TAG, task.getException().getMessage()); //Never ignore potential errors!
}
}
});
Greeting everyone, im working a project right now and need help for firebase realtime database.
My firebase Project
As you guys can see in the above picture, inside student, I have matric number, and inside matric number have block and department.
I have a barcode scanner which scan the value of department and return to get the matric number. Any solution.
Below code is my progress.
mCodeScanner.setDecodeCallback(new DecodeCallback() {
#Override
public void onDecoded(#NonNull final Result result) {
runOnUiThread(new Runnable() {
#Override
public void run() {
r = result.getText();
Query s = ref.equalTo("JTMK", "department");
name.setText(r);
}});}});
If you don't know the matric number of the student, indeed a query is required. Assuming that result.getText() returns JTMK, please use the following lines of code:
mCodeScanner.setDecodeCallback(new DecodeCallback() {
#Override
public void onDecoded(#NonNull final Result result) {
String department = result.getText();
DatabaseReference db = FirebaseDatabase.getInstance().getReference();
DatabaseReference studentRef = db.child("Student");
Query queryByDepartment = studentRef.orderByChild("department").equalTo(department).limitToFirst(1);
queryByDepartment.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
for (DataSnapshot ds : task.getResult().getChildren()) {
String block = ds.child("block").getValue(String.class);
name.setText(block);
Log.d("TAG", block);
}
} else {
Log.d("TAG", task.getException().getMessage()); //Never ignore potential errors!
}
}
});
}
});
Things to notice:
There is no need to use runOnUiThread when reading data from the Realtime Database.
Firebase API is asynchronous. So I recommend you read the following resource:
How to read data from Firebase Realtime Database using get()?
When you run the code, you should see in the logcat BESTARI 4, which will also be set to name TextView.
So I am working on the memories Firebase app and there is a stage where the user can upload photos to his memory. Each photo has uniq name "ImgLink0","ImgLink1",etc..
The function I am working on is to delete a specific photo when I am pressing a long click, but I can't reach the image in Firebase.
I tried like below but I got stuck because I can't identify the image key:
mDatabase.child(userUID).child("Memories").child(memoryName).child("Images").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot imageSnapshot : dataSnapshot.getChildren()) {
String imagesKey = imageSnapshot.getKey();
String imagesValue = (String) imageSnapshot.getValue();
Log.e("Test","" + imagesKey + "" + imagesValue);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
And this is the data structure:
I tried using query too but with no success because I don't have the image key.
Thank you for any help :)
To delete a node from the database, you need to know the completely path to that node.
Assuming you do know the URL of the image to delete, but not the key (ImgLink1 or ImgLink2) that is stored under, you're going to have to use a query to look up that key.
Something like:
DatabaseReference ref = mDatabase.child(userUID).child("Memories").child(memoryName).child("Images");
Query query = ref.orderByValue().equalTo("URL of the image")
query..addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot imageSnapshot : dataSnapshot.getChildren()) {
imageSnapshot.getRef().removeValue();
}
}
...
Also see these related answer:
deleting specific post in database(by post node) but it deletes entire database_table
How can i remove all fields and values by using key value or a field key from firebase realtime database?
To remove the second URL for example, please use the following lines of code:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference imageToDeleteRef = rootRef
.child(uid)
.child("Memories")
.child("TestMem")
.child("Images")
.child("ImgLink1");
imageToDeleteRef.removeValue().addOnCompleteListener(/* ... */);
So I have created a reference that points exactly to ImgLink1 node and then I called .removeValue() on reference in order to delete it. So there is no need to read the value in order to perform a delete operation.
If you want to read the URL, please use these lines:
imageToDeleteRef.addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
String url1 = task.getResult().child("ImgLink1").getValue(String.class);
Log.d("TAG", url1);
} else {
Log.d("TAG", task.getException().getMessage()); //Don't ignore potential errors!
}
}
});
The result in the logcat will be:
https://firebasestorage.googleapis.com...
Hello I create a small social network for my high school and I use android studio and firebase as server for the data.My database structure for Users info - / (Users)
- /James/
–- /james-uid/
- /David/
–- /james-uid/
I added the possibility of blocking users. My database is structured
- / (root)
- /UsersIblocked/
–- /james-uid/
-- /jake-uid/
-- /David-uid/
-- /Karl-uid/
, now I would like that when my application displays posts that the publications of the users that we blocked does not appear .
to make the publications appear I use this code ( This code should take the uid of the person who posted the post and see if this uid is in our blocked list and if there is, it should not take the post)
mAuth = FirebaseAuth.getInstance();
ArrayList<PostClass> PostArray= new ArrayList<>();
Listview = new PostAdapter(getActivity(),R.layout.itempost, PostArray );
mDatabase = FirebaseDatabase.getInstance().getReference().child("Blog");
mDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Log.d(TAG, "getPost: found post user: " + snapshot);
PostClass post = snapshot.getValue(PostClass.class);
DatabaseReference blockDatabase = FirebaseDatabase.getInstance().getReference().child("BlockedUsers").child("UsersIBlocked").child(mAuth.getCurrentUser().getUid());
blockDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (!dataSnapshot.child(post.getuid).exists()){
PostArray.add(post);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Collections.reverse(PostArray);
Listview.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Post is the class that I use to receive the data on the publication, post.getuid gives me the uid of the person who published the publication
But nothing happens when I use this code, so if someone can help me thank you
You should call Listview.notifyDataSetChanged(); whenever the data set of the list view has changed. Since you're loading data in a nested addListenerForSingleValueEvent, you should call it in the onDataChange() of that listener:
blockDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (!dataSnapshot.child(post.getuid).exists()){
PostArray.add(post);
Listview.notifyDataSetChanged();
}
}
...
Also note that it's a really bad practice to leave onCancelled empty, as it hides potential problems. The simplest implementation is:
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
Query sqlite = mDatabaseReference.child("Messages").child(MessageSenderId).child(MessageRecieverId);
sqlite.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChild("Message")) {
String msg = dataSnapshot.child("Message").getValue().toString();
String from = dataSnapshot.child("From").getValue().toString();
String time = dataSnapshot.child("Time").getValue().toString();
} else {
Toast.makeText(getApplicationContext(), "NULLLL", Toast.LENGTH_SHORT).show();
}
Database
This is the most basic thing in the database. I have never got a problem with childEvent or valueEvent and i want a single event for now and I'm not able to fetch.
There is no error because i have put an if statement and it shows toast as null which means dataSnapshot doesn't have a child named messages but it's right there. I tried putting a for loop too, but didn't work
You have not given the full reference. There is a list of push keys and you have to use a foreach loop.
Query sqlite = mDatabaseReference.child("Messages").child(MessageSenderId).child(MessageRecieverId);
sqlite.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot vinSnapshot : dataSnapshot.getChildren()) {
if (vinSnapshot .hasChild("Message")) {
String msg = dataSnapshot.child("Message").getValue().toString();
String from = dataSnapshot.child("From").getValue().toString();
String time = dataSnapshot.child("Time").getValue().toString();
} else {
Toast.makeText(getApplicationContext(), "NULLLL", Toast.LENGTH_SHORT).show();
}
}
Or you can store all data into ArrayList then perform your task.