Ordering collectionGroup by serverTimestamp - android

I have made a database using Firestore.
The data base is as follows:
There is a main collection called NBDB, inside there are documents with uid for each user (for example OJQRFOyYd....). Inside each document there is another collection called MyBooks and inside this collection there are documents with uid that contain the BookID, DateCreated and Popularity.
By using the following code I have managed to obtain all of the BookIDs thank to collectionGroup query:
FirebaseFirestore db = FirebaseFirestore.getInstance();
db.collectionGroup( "MyBooks" ).get()
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
for (QueryDocumentSnapshot document : queryDocumentSnapshots) {
Log.d(TAG,document.getId() + " => " + document.getData().get( "BookID"));
}
}
});
However, I had like the data to be ordered by the DateCreated field.
I thought first to order the database and then to use the function above, something like:
FirebaseFirestore db = FirebaseFirestore.getInstance();
db.collectionGroup( "MyBooks" ).orderBy("DateCreated").get()
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
for (QueryDocumentSnapshot document : queryDocumentSnapshots) {
Log.d(TAG,document.getId() + " => " + document.getData().get( "BookID"));
}
}
});
However it is not working since my search is not inside the document of each book.
Is there a way to do it?
Thank you

Related

Read and write data to Cloud Firestore in Android

Hi I want to read and write data using Firebase Firestore.
1- I `added Firebase to my project (using this instruction)
2- I added Firestore to my project (using this instruction)
I can write and then read data, but the read and write operation are locally and my Firestore database not changing.
I have added google-services.json to my app directory
I declared internet and network-state permission in manifest
My device is connected to internet
My Firestore database is in test mode (allow read, write)
This is my build.gradle dependency:
implementation platform('com.google.firebase:firebase-bom:29.1.0')
implementation 'com.google.firebase:firebase-analytics'
implementation 'com.google.firebase:firebase-firestore'
This is my code to add data to Firestore database:
private void writeData()
{
FirebaseFirestore db = FirebaseFirestore.getInstance();
Map<String, Object> user = new HashMap<>();
user.put("first", "Ada");
user.put("last", "Lovelace");
user.put("born", 1815);
db.collection("purchased")
.add(user)
.addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
#Override
public void onSuccess(DocumentReference documentReference) {
Toast.makeText(MainActivity.this,"done",Toast.LENGTH_SHORT).show();
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(MainActivity.this,"failed",Toast.LENGTH_SHORT).show();
}
});
}
And this is my code to read data:
private void readData()
{
FirebaseFirestore db = FirebaseFirestore.getInstance();
db.collection("purchased")
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
Toast.makeText(MainActivity.this,document.getId() + " => " + document.getData(),Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(MainActivity.this,"Error getting documents: "+ task.getException().getMessage().toString(),Toast.LENGTH_LONG).show();
}
}
});
}
While writing data, even callbacks are not calling (neither onSuccess nor onFailue) and no toast is displaying, but when I read data the toast display my data correctly, but everything is offline and no changes made to my Firestore database, what's the problem?

How to get collection and subcollction from parent collection in cloud firestore android

I have user_info as parent collection. Under this parent collection it has single_list as child collection and some information. I want to get all values from parent collection. Please help me to find answer.
Thanks in advance
I think your use of terminology is a bit off. You have a collection of user_info documents, and each of those documents has a sub-collection named single_data.
The difference here is that there isn't a single single_data subcollection. There is one subcollection for each user_info document.
Since the subcollection has a static name, what you are looking to do is pretty straightforward using a collection group query.
firebase.firestore().collectionGroup('single_data')
.get()
.then((querySnapshot) => {
// Do something with the docs from across all the subcollections
})
FirebaseFirestore db = FirebaseFirestore.getInstance();
db.collection("users_info")
.get()
.addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
for (DocumentSnapshot document : task.getResult()) {
//Here you can add all documents Id to your documentIdList to fetch all sigle_data at once.
Log.d(TAG, document.getId() + " => " + document.getData());
documentIdList.add(document.getId());
}
getAllSubCollSingleData(documentIdList);
} else {
Log.w(TAG, "Error getting documents.", task.getException());
}
}
});
public void getAllSubCollSingleData(List<Int> documentIdList){
for(int i=0;i<documentIdList.size();i++){
db.collection("users_info").document(documentIdList.get(i))(would be phone number)
.collection("single_data")
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
//Here you can get all documents in sub collection single_data
}
} else {
Log.w(TAG, "Error getting documents.", task.getException());
}
}
});
}}

Check for document existence in Firestore

I'm trying to find if some item exists in my database.
If it does not exist, I had like to add it.
If it exists, I had like to show a message.
The code im using:
CollectionReference colRefMyBooks = db.collection( "Users" ).document( auth.getUid() ).collection( "MyBooks" );
Query queryMyBooks = colRefMyBooks.whereEqualTo("BookID", bookId);
queryMyBooks.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
Toast.makeText(BookDetailActivity.this, "Book already in my list", Toast.LENGTH_SHORT).show();
}
} else {
db.collection( "Users" ).document( auth.getUid() ).collection( "MyBooks" ).add( general_book );
}
}
});
This code works good as long as there is a collection "MyBooks". However, if there is no collection "Mybooks" I want it to consider it as the task is not successful and therefore to add the item.
What I do get is that it skips the whole onComplete and therefore does not add anything.
Does it mean that I have to check first if a collection exists and inside of it if document?
Thank you
A query that finds no documents will always be considered "successful", regardless of whether or not any collections exist. This behavior can't be changed.
What you'll have to do instead is check if there are no documents in the result set and decide what you want to do from there:
queryMyBooks.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
QuerySnapshot snapshot = task.getResult();
if (snapshot.isEmpty()) {
db.collection( "Users" ).document( auth.getUid() ).collection( "MyBooks" ).add( general_book );
}
else {
for (QueryDocumentSnapshot document : snapshot) {
Toast.makeText(BookDetailActivity.this, "Book already in my list", Toast.LENGTH_SHORT).show();
}
}
}
}
});
Note that collections don't really "exist". There are no operations to add or delete collections. There are just operations to modify documents. A collection only appears in the console if it contains at least one document. If it contains no documents, it just disappears.

Firebase Listener Skip

I have converted to Firebase for my Android development as I want to utilise the many features of Firebase (Notifications, Messaging, Storage etc), however, I am having difficulty receiving data from Firebase and cannot find detailed information online. Yes, I have tried the documentation but it does not explain the events I am experiencing.
I want to retrieve all the data that I have an insert it into an arraylist of objects. Here is a static example:
users[i] = new User("James" + (i*2.5), "Hmack00" + (i*2), "https://firebasPic_2019.03.03.05.26.35.jpg.jpg?alt=media&token=cf", "United Kingdom");
Database:
{
"Users" : {
"4PdlTlv3qjZ3BmDvrJyUut9Fnq43" : {
"Country" : "xx",
"Fullname" : "hh",
"ProfilePicture" : "htm/o/Images%2FSearchAdapter%2F4PdlTlv3qjZ3BmDvrJyUut9Fnq43%2FProfilePicture%2FProfilePic_2019.03.06.10.47.54.jpg.jpg?alt=media&token=b647708e-c6d5-4b45-bef0-3dc40301b73a",
"Username" : "hmack001"
},
"COg4r4io9hezhFpmK3adPucUXA93" : {
"Country" : "spain",
"Fullname" : "nat",
"ProfilePicture" : "hcom/o/Images%2FSearchAdapter%2FCOg4r4io9hezhFpmK3adPucUXA93%2FProfilePicture%2FProfilePic_2019.03.06.19.14.17.jpg.jpg?alt=media&token=8620b321-5cef-42f0-a828-dbb7c37c8e7d",
"Username" : "nat"
},
"Tw1xRxViygNsLqrQiaaMAvAduIu1" : {
"Country" : "uk",
"Fullname" : "harvey\n",
"ProfilePicture" : "t.com/o/Images%2FUsers%2FTw1xRxViygNsLqrQiaaMAvAduIu1%2FProfilePicture%2FProfilePic_2019.03.03.05.26.35.jpg.jpg?alt=media&token=c290e75a-5f92-4271-bcb5-c644fe1b14ef",
"Username" : "RGB"
},
"vOxr1RoDqgWogKK1lp9pfpTHc6w2" : {
"Country" : "scotland ",
"Fullname" : "greg greg",
"ProfilePicture" : "ot.com/o/Images%2FSearchAdapter%2FvOxr1RoDqgWogKK1lp9pfpTHc6w2%2FProfilePicture%2FProfilePic_2019.03.04.12.30.22.jpg.jpg?alt=media&token=27b024cf-0691-4121-8a27-26acf101ebc2",
"Username" : "greg"
},
"xecUOPeyMcQaQrgkU9ouDgK90Ai1" : {
"Country" : "ggh",
"Fullname" : "Da apply ",
"ProfilePicture" : "2FProfilePic_2019.03.03.04.58.50.jpg.jpg?alt=media&token=f35854c2-3ff9-4d18-9f7a-10c13f066c68",
"Username" : "gg"
}
}
}
Here is my code and I will explain my errors after (I have left in 'zombie' code, to show the attempts that I have made)
//Firebase Variables
private FirebaseDatabase mFirebaseDatabase;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private DatabaseReference myRef;
//Firebase Data
mAuth = FirebaseAuth.getInstance();
mFirebaseDatabase = FirebaseDatabase.getInstance();
userId = mAuth.getCurrentUser().getUid();
myRef = mFirebaseDatabase.getReference().child("Users").child(userId);
//Firebase Data
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) { //Function called every time a change is made to the database
showData(dataSnapshot);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) { //Function called when there is an error in the database/ with the call
Log.d("Print","Cancelled Firebase: " + databaseError.toString());
}
});
}
private void showData(DataSnapshot dataSnapshot) {
int userCount = 5;
int i = 0;
for (DataSnapshot ds : dataSnapshot.getChildren()) {
//User user = new User();
//User user = new User(); //Get Count of Firebase Users
//user = new User();
if (ds.child(userId).exists()) {
/*user.setFullname(ds.child(userId).getValue(User.class).getFullname()); //set the full name
user.setUsername(ds.child(userId).getValue(User.class).getUsername()); //set the username
user.setProfilePicture(ds.child(userId).getValue(User.class).getProfilePicture()); //set the profile picture
//Display Information
Log.d("DataSnapchat Test", "ShowData Name: " + user.getFullname());
Log.d("DataSnapchat Test", "ShowData Username: " + user.getUsername());
Log.d("DataSnapchat Test", "ShowData Picture: " + user.getProfilePicture());
ArrayList<String> userArrayList = new ArrayList<>();
userArrayList.add(user.getFullname());
userArrayList.add(user.getUsername());
userArrayList.add(user.getProfilePicture());
*/
String fullname = (String) ds.child(userId).child("Fullname").getValue();
Toast.makeText(this, "Fullname: " + fullname, Toast.LENGTH_SHORT).show();
//UserListAdapter adapter = new UserListAdapter(this, R.layout.find_profiles_search, userArrayList, mProfileSearch);
//mListView.setAdapter(adapter);
i++;
}
}
}
When I debug the code the showData function is never called and neither functions within the Value Event Listener are called, is this an Async Problem?
Currently I am trying to fetch data and insert it into a variable (Literally any data, once I have a working query I can convert it to fit by manipulating child fields etc).
Question: Does the addValueListener only work when data is changed in the database? If so then what is the alternative, if not then why are the functions not operating.
I do not recieve any errors and nothing is logged to the console.
I want to put my database into an array list, I know that I shouldnt use getChildren to do this, put I am trying to test if I can get any data before I try and get all the data.
You have some really weird loops in showData(). Since you're attaching a ValueEventListener to the node of the specific user, you can just look up the property values for that specific user:
myRef = mFirebaseDatabase.getReference().child("Users").child(userId);
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d("OnDataChange", dataSnapshot.getKey());
Log.d("OnDataChange", dataSnapshot.child("Fullname").getValue(String.class));
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d("Print","Cancelled Firebase: " + databaseError.toString());
}
});

Firebase Firestore Nested Query retrieving both results

So I'm trying to get results from firestore
db.collection("dialogs")
.whereArrayContains("members", me.getId())
.get()
.continueWith(continue -> {
List<Task<DocumentSnapshot>> tasks = new ArrayList<>();
for (DocumentSnapshot snapshot : continue.getResult())
for (Object userId : (ArrayList) snapshot.get("members"))
tasks.add(db.collection("users").document(userId.toString()).get());
return tasks;
})
.addOnSuccessListener(task -> {
for (Object something : task)
Log.d("Query", "Data: " + something);
})
.addOnFailureListener(e -> Log.d("Query", "Exception: " + e));
this code will give me the users documents as seen above, what i want as well is the document id of snapshot
To be clear, continue isn't a document, it's a Task that contains a DocumentSnapshot result. Your DocumentSnapshot is in snapshot, and you can get the id of a DocumentSnapshot using its getId() method.
val id = snapshot.getId()

Categories

Resources