How to query a DocumentRefrence in Firestore? - java

I'm new in firebase Firestore and when i tried to write this code with Firestore I faced a problem.
DatabaseReference mDisplayData = FirebaseDatabase.getInstance().getReference().child("Users").child(postKey);
com.google.firebase.database.Query firstQuery = mDisplayData.limitToFirst(20);
firstQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
String nameData = dataSnapshot.child("name").getValue().toString();
String statusData = dataSnapshot.child("status").getValue().toString();
String imageData = dataSnapshot.child("thumb_image").getValue().toString();
userViewHolder.setDetails(getApplicationContext(),nameData,statusData,imageData);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
the problem was in this line of code :
Query firstQuery = firebaseFirestore.collection("Users").document(postKey).collection(null);
what i want to do is to create a firestore query but i want to stop only in postkey refrence the thing that is not possible what should i do.
please help and thank you.

firstQuery in the following line of code:
Query firstQuery = firebaseFirestore.collection("Users").document(postKey).collection(null);
Is of type Firestore Query and is not of type Firebase real-time database Query. So there is no way in which you can call addListenerForSingleValueEvent() on such an object. What you are actually trying to do, is to use code that can get the data from Firebase real-time database on Firestore query, which obviously is not possible.
To solve this, you need to use a get() call on your firstQuery object and then attach a listener. But first I recommend you read the official documentation regarding getting data with Cloud Firestore.

Related

How to update entry in Firebase Database based on an attribute value

I am using the Firebase Realtime Database with Android in Java. I have the following database screenshot:
I would like to change the availability value (from 0 to 1) for the ingredient with the attribute "ingredient_name = Lime". The attribute ingredient_name is actually something like a primary key meaning that there will be no other database entry with this specific name.
I tried the following code
DatabaseReference rootRef;
rootRef = FirebaseDatabase.getInstance("https://....app").getReference();
String ingredientToBeUpdate = "Lime";
rootRef.child("ingredients").orderByChild("ingredient_name").equalTo(ingredientToBeUpdate).child("availability").setValue(1);
But I get the error "Cannot resolve method 'child' in 'Query'". Can you tell me how to do this update properly? So I would like to update the value from the database entries who attribute "ingredient_name" is equal to a certain string ingredientToBeUpdate.
Firebase doesn't support so-called update queries, where you send a condition and the new data to the database and it them writes the new data for all nodes matching the condition.
Instead you will need to execute the query in your application code, loop through the results, and update each of them in turn:
rootRef
.child("ingredients")
.orderByChild("ingredient_name")
.equalTo(ingredientToBeUpdate)
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot ingredientSnapshot: dataSnapshot.getChildren()) {
ingredientSnapshot.getRef().child("availability").setValue(1);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
}
Also see:
Firebase Android, set value where x = x?
Is it possible to update a specific child's value without ID or key in firebase realtime database from android on button click?

How can I perform OR query while searching in firebase?

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

How to Query Firebase by child and equalTo in Android? [duplicate]

This question already has answers here:
Firebase Query Double Nested
(3 answers)
Closed 2 years ago.
I have "orderStatus" node type integer in my database, and I need to query it by its value(0, 1, 2, etc.). It works okay if I user orderByChild("orderStatus"), but I don't want to be downloading all data and order it, I just want to download data with specific "orderStatus". That's where I run to my problem, when I put equalTo(statusInteger) I don't get any data from the database.
What am I doing wrong, am I using equalTo wrong or something?
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Orders");
Query orderRef = databaseReference
.child(restaurantId)
.orderByChild("orderStatus")
.equalTo(0);
orderRef.addListenerForSingleValueEvent...
To be able to query the database by a specific property, you need to add all child names that exist in that particular hierarchy. In your query, you are missing a child. Between the "restaurantId" node and the actual Order object, which holds the "orderStatus" property, there is one more node, which is "LPG ... CQ2", and I'm assuming the UID of the logged-in user. To make it work, please use the following lines of code:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference uidRef = rootRef.child("Orders").child("Restaurant01").child(uid);
Query orderStatusQuery = uidRef.orderByChild("orderStatus").equalTo(0);
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String userName = ds.child("userName").getValue(String.class);
Log.d("TAG", userName);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d("TAG", databaseError.getMessage()); //Don't ignore potential errors!
}
};
orderStatusQuery.addListenerForSingleValueEvent(valueEventListener);
The result in the logcat will be:
User
Edit:
According to your comment, what you are looking for it's actually not possible with your actual database structure. Besides that, filtering on the client it's definitely not an option in this scenario.
However, the best I can think of is to create another node that stores all orders, of all users. In this way, you can query using ".orderByChild("orderStatus").equalTo(0)" and you'll get the desired results. This practice is called denormalization and is a common practice when it comes to Firebase. For a better understanding, I recommend you see this video, Denormalization is normal with the Firebase Realtime Database.
what if you Start with .equalTo(... ) then .orderBy(...)?

Firebase DataSnapshot.getValue() is null

I've been looking at the other errors here in SO, in regards to mine and still can't seem to get anywhere, since I keep getting the DataSnapshot.getValue() returning null...
First I get the db-ref:
private DatabaseReference f_database = FirebaseDatabase.getInstance().getReference().child("maps_data");
Then in my OnCreate method inside my activity I've added a listener:
f_database.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){ <<<< Problem is here, value is null
for(DataSnapshot snapshot:dataSnapshot.getChildren()){
double lati = 0;
// Get UsersLocationFavorites object and use the values to update the UI
UsersLocationFavorites userLocFav = snapshot.getValue(UsersLocationFavorites.class);
LatLng location = new LatLng(userLocFav.getFavoriteSpot().getLatitude(), userLocFav.getFavoriteSpot().getLongitude());
gmap.addMarker(new MarkerOptions().position(location).title("Old Marker"));
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
And looking inside my firebase database, I have the following:
I've double checked spellings ("maps_data"), I've looked an many SO-problems here, where I can't find one that fits my problem.
Can anyone see, what I've done wrong?
You're mixing up the databases provided by Firebase.
All the code you're showing is accessing Firebase Realtime Database. But the screenshot is showing data in Firestore. These are completely diffrent database products. If you want to read data out of Firestore, you should be using the Firestore SDK instead.

What is the best way to update a record getting the key from another table?

I am learning how realtime databases work, so be patient.
To better explain my doubt, I take an image showing the relevant part of the realtime database
https://prnt.sc/p0wmvs
All I want is the best way to update the field "name" of a record "grps".
The starting point is the "usrs" table where I can reference
mFD.getReference("usrs/"+user.getUid()+"/asAdm/grps/"+grpId)
My function to update "name" of group name
public void editGroupFromUser(long grpID, Group group, final DataStatus dataStatus) {
DatabaseReference mFRUser = mFirebaseDatabase.getReference(
"usrs/"+user.getUid()+"/asAdm/gprs/"+grpID
);
mFRUser.child("grp").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String groupKey = (String) dataSnapshot.getValue();
DatabaseReference mFRGroup = mFirebaseDatabase.getReference("grps");
mFRGroup.child( groupKey ).setValue(group).addOnSuccessListener(aVoid -> {
dataStatus.DataIsUpdated();
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
The need to receive the group key to then send the group update. This does not seem efficient at all.
Also, the need to send the user Uid key when the user is identified in firebase does not seem safe at all.
Is there any better way to do this?

Categories