Store subcollection data in Firestore - java

I have a problem on to add a subcollection "Diary" under collection "Users". How to make it so that one user can have several diary?
Here's Java codes:
check.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirebaseUser user = fAuth.getCurrentUser();
String uid = user.getUid();
DocumentReference df = fStore.collection("Diary").document(user.getUid());
Map<String, Object> diaryInfo = new HashMap<>();
diaryInfo.put("Symptom", symptom.getEditText().getText().toString());
diaryInfo.put("UID", uid);
diaryInfo.put("Note", note.getEditText().getText().toString());
diaryInfo.put("Date", dateButton.getText().toString());
SimpleDateFormat tf = new SimpleDateFormat("hh:mm a");
String currentTime = tf.format(Calendar.getInstance().getTime());
time.setText(currentTime);
diaryInfo.put("Time",time.getText().toString());
feeling = spinner.getSelectedItem().toString();
diaryInfo.put("Feeling", feeling);
df.set(diaryInfo).addOnSuccessListener(new OnSuccessListener() {
#Override
public void onSuccess(Object o) {
Toast.makeText(add_diary_user.this, "Data successfully stored", Toast.LENGTH_SHORT).show();
startActivity(new Intent(add_diary_user.this, diary_user.class));
finish();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(add_diary_user.this, e.toString(), Toast.LENGTH_SHORT).show();
}
});
}
});
Database structure:

You should place your subcollection inside the corresponding document of your parent collection:
// Create a reference to a new 'Diary' document at Users/user_id/Diary/doc_id
// with an auto-generated document id
DocumentReference df = fStore.collection("Users").document(user.getUid()).collection("Diary").document();
When you need to retrieve the diaries, query the individual user's Diary collection:
fStore.collection("Users").document(user.getUid()).collection("Diary")
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
// Do something with your retrieved documents
}
}
}

Related

How do I retrieve data under UID for the signed in user with Firebase

I saved some data under a node with the currently signed in user UID, along with the post timestamp.I successfully manage to retrieve all the data under this node, but I would only like to retrieve the data for the currently signed in user, I am trying to create something similar to how amazon stores an item in the cart and when the user clicks the cart it shows the items they have added there, not all the items for every user. Can someone assist me with this problem?
public void addItemToCart(){
SimpleDateFormat formatter = new SimpleDateFormat(" HH:mm:ss ");
Date date = new Date(System.currentTimeMillis());
timeStamp = loggedInUserId + formatter.format(date);
userDictionary.put("itemPrice", selectedPrice);
userDictionary.put("productname",productNameText);
userDictionary.put("description", selectedStringProductDescrtipon);
userDictionary.put("uid",loggedInUserId);
userDictionary.put("productImage", selectedImage);
userDictionary.put("datee",date.toString());
userDictionary.put("name",loggedInUserName);
userDictionary.put("timestamp",timeStamp);
uploadPostRef.child("Cart").child(timeStamp).setValue(userDictionary).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void unused) {
Log.i("sucessfully added","sucesssfully added to cart..");
getLoggedInUserData();
}
});
numberInCartIv.setVisibility(View.VISIBLE);
public void downloadCartData(){
cartDb.child("Cart").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot data : dataSnapshot.getChildren()) {
if (data.exists()) {
Log.i("data",data.toString());
// cartModel = data.getValue(CartModel.class);
// cartModelArrayList.add(cartModel);
// LinearLayoutManager horizontalLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
// cartRecyleView.setLayoutManager(horizontalLayoutManager);
// cartAdapter = new CartAdapter(cartModelArrayList, getContext());
// cartRecyleView.setAdapter(cartAdapter);
} else {
Log.i("error", "Error Loading JSON data..");
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
String error = databaseError.getDetails();
Log.i("error", error);
}
});
}
First of all, you need to change your DB json to this one.
Cart
-userUid
-cartUid
-datee
-description
-andSoOn
That's mean, when you are storing the item into Cart. You need to include the userUid.
//Getting userUid
final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
if (firebaseUser != null) {
final String userUid = firebaseUser.getUid();
uploadPostRef.child("Cart").child(userUid).child(timeStamp).setValue(userDictionary).addOnSuccessListener(new OnSuccessListener() {
#Override
public void onSuccess(Void unused) {
Log.i("sucessfully added","sucesssfully added to cart..");
getLoggedInUserData();
}
});
}
To retrieve the Cart according to the user. You just call them like this.
public void downloadCartData(){
cartDb.child("Cart").child(userUid).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot data : dataSnapshot.getChildren()) {
if (data.exists()) {
Log.i("data",data.toString());
} else {
Log.i("error", "Error Loading JSON data..");
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
String error = databaseError.getDetails();
Log.i("error", error);
}
});
}

Retrieve subcollection data from Firestore in Android

I keep failed to retrieve the data from subcollection "Diary" when trying on click on a RecyclerView. What I want is when I on click on a RecyclerView, it will display that data stored in the "Diary". What's the problem with my codes?
RecyclerView Java codes:
private void setUpRecyclerView() {
fStore = FirebaseFirestore.getInstance();
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
Query query = fStore.collection("Users").document(user.getUid()).collection("Diary").orderBy("Date", Query.Direction.ASCENDING);
FirestoreRecyclerOptions<ModelClass> options = new FirestoreRecyclerOptions.Builder<ModelClass>()
.setQuery(query, ModelClass.class)
.build();
adapters = new CustomAdapter(options,this);
adapters.startListening();
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapters);
new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0,
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
adapters.deleteItem(viewHolder.getAdapterPosition());
}
}).attachToRecyclerView(recyclerView);
}
#Override
public void onItemClick(final DocumentSnapshot snapshot, int position) {
final ModelClass diary = snapshot.toObject(ModelClass.class);
String id = snapshot.getId();
startActivity(new Intent(diary_user.this,onClickRecyclerViewDiary_user.class));
Toast.makeText(diary_user.this,"Position: " + position + "ID: " + id,Toast.LENGTH_SHORT).show();
}
Stored data Java codes:
check.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirebaseUser user = fAuth.getCurrentUser();
String uid = user.getUid();
String id = fStore.collection("Users").document(user.getUid()).collection("Diary").document().getId();
DocumentReference df = fStore.collection("Users").document(user.getUid()).collection("Diary").document(id);
Map<String, Object> diaryInfo = new HashMap<>();
diaryInfo.put("Symptom", symptom.getEditText().getText().toString());
diaryInfo.put("Note", note.getEditText().getText().toString());
diaryInfo.put("Date", dateButton.getText().toString());
diaryInfo.put("ID",id);
SimpleDateFormat tf = new SimpleDateFormat("hh:mm a");
String currentTime = tf.format(Calendar.getInstance().getTime());
time.setText(currentTime);
diaryInfo.put("Time", time.getText().toString());
feeling = spinner.getSelectedItem().toString();
diaryInfo.put("Feeling", feeling);
df.set(diaryInfo).addOnSuccessListener(new OnSuccessListener() {
#Override
public void onSuccess(Object o) {
Toast.makeText(add_diary_user.this, "Data successfully stored", Toast.LENGTH_SHORT).show();
startActivity(new Intent(add_diary_user.this, diary_user.class));
finish();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(add_diary_user.this, e.toString(), Toast.LENGTH_SHORT).show();
}
});
}
});
Retrieve data Java codes:
private void getDiary() {
fStore = FirebaseFirestore.getInstance();
FirebaseUser user = fAuth.getCurrentUser();
String id = fStore.collection("Users").document(user.getUid()).collection("Diary").document().getId();
fStore.collection("Users").document(user.getUid()).collection("Diary");
diary.whereEqualTo("ID", id)
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (DocumentSnapshot document : task.getResult()) {
// Do something with your retrieved documents
dateButton.setText((CharSequence) document.getString("Date"));
note.getEditText().setText((CharSequence) document.getString("Note"));
symptom.getEditText().setText((CharSequence) document.getString("Symptom"));
}
}
}
});
}
Database structure:
Output:
I believe the problem in your code is in this line:
String id = fStore.collection("Users").document(user.getUid()).collection("Diary").document().getId();
Where you are using .document().getId(); but without specifying which document you want, which makes id not have the expected value and because of that you don't get any results in the comparison that uses that value later in your execution. To fix that you would need to have this Id stored somewhere and pass it as a parameter to your getDiary() function, or something similar to that.

How to get document id Firestore?

I was trying to get document id for updating a data, but instead it create a new document id. How to get document id Firestore?
Code :
final String getID = firebaseFirestore.collection("Users").document(currentUser.getUid()).collection("Documents").document().getId();
buttonUpdate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final String inspectorName = editInspector.getText().toString().trim();
final String marketLocation = editLocation.getText().toString().trim();
progressUpdated.show();
firebaseFirestore.collection("Users").document(currentUser.getUid()).collection("Documents").document(getID).update("inspectorName", inspectorName, "marketLocation", marketLocation).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(StartCounting.this, "Document updated", Toast.LENGTH_SHORT).show();
progressUpdated.dismiss();
dialogUpdate.dismiss();
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(StartCounting.this, "Error : " + e.toString(), Toast.LENGTH_LONG).show();
progressUpdated.dismiss();
}
});
}
});
It is not updating because :
The following code of line generates new id when you call the getID each time you call it and store in String.
String getID = firebaseFirestore.collection("Users").document(currentUser.getUid()).collection("Documents").document().getId();
So i suggest you to store the id which you get from getID store under each user document. Something like when you create / generate document just add the String value of id under the userid field.

How to display specific data of current user from firebase to new activity?

I have a problem with my codes whereby I cannot display data (input from the previous activity) to a new activity.
this is my data in the firebase
this is my current output, the BMI is null
what I want is this, the BMI value is not null
Here is my current code of HomepageActivity:
private void viewBMI() {
FirebaseDatabase database = FirebaseDatabase.getInstance();
final String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference myRef = database.getReference("Users").child("bmi").child(uid);
// Read from the database
myRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String finalBmi = (String) dataSnapshot.getValue();
showBMI.setText("BMI: " + String.valueOf(finalBmi));
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
// Failed to read value
//Log.w(BMI, "Failed to read value.", error.toException());
}
});
This is the code from previous activity:
private void updateBMI(double bmi, final FirebaseUser currentUser) {
kg = Double.parseDouble(inputKg.getText().toString());
m = Double.parseDouble(inputM.getText().toString());
metricFormula = new MetricFormula(kg, m);
imperialFormula = new ImperialFormula(kg, m);
//bmi = String.valueOf(TWO_DECIMAL_PLACES.format(metricFormula.computeBMI(metricFormula.getInputKg(),metricFormula.getInputM())));
bmi = Double.parseDouble(TWO_DECIMAL_PLACES.format(metricFormula.computeBMI(metricFormula.getInputKg(),metricFormula.getInputM())));
final double finalBmi = bmi;
mAuth.updateCurrentUser(currentUser).addOnCompleteListener(this, new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
UserProfileChangeRequest profileUpdate = new UserProfileChangeRequest.Builder()
.build();
currentUser.updateProfile(profileUpdate)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
Map<String, Object> values = new HashMap<>();
values.put("bmi", finalBmi);
FirebaseDatabase.getInstance().getReference("Users")
.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
.updateChildren(values).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
//progressBar.setVisibility(View.GONE);
if (task.isSuccessful()) {
//acc successfully registered
showMessage("Account Updated");
updateUI();
}
else{
}
}
});
}
}
});
}
});
}
//next page
private void updateUI() {
Intent homepageActivity = new Intent(EditProfileActivity.this,HomepageUser.class);
//homepageActivity.putExtra("bmi",bmi); //new
startActivity(homepageActivity);
finish();
}
I think,
Your reference is not reaching correctly
DatabaseReference myRef = database.getReference("Users").child("bmi").child(uid);
there is no child "bmi" under "Users"
In your image, you have
Users -> JKkaSDGLdkM7HxzBKf1ivJ4G6A03 -> bmi...etc
there is another layer you need to account for reaching the information.
Your order of child access is incorrect. As i can see in the image of Firebase Child Hierarchy you have 'bmi' under 'userID'. So replace
DatabaseReference myRef = database.getReference("Users").child("bmi").child(uid);
with
DatabaseReference myRef = database.getReference("Users").child(uid).child("bmi");
Since hierarchy structure is Users->id->bmi(a component of jason object)

android firestore: retrieve custom object from HashMap

I would like to store userdata in a document in Firestore. To do that I’m using a HashMap:
String userID = mAuth.getCurrentUser().getUid();
User user = new User(stringMail, stringUsername, stringGender, stringBirthday,
stringCountry, registeredOn);
HashMap<String, User> userHashMap = new HashMap<>();
userHashMap.put("userdata", user);
users.document(userID).set(userHashMap, SetOptions.merge())
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(RegisterActivity.this, "Upload completed to Firestore!", Toast.LENGTH_LONG).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(RegisterActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(RegisterActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
});
That works pretty good. I do have a problem though with retrieving the data. As the data is stored in a HashMap I can’t use following code:
String userID = mAuth.getUid();
users.document(userID).get()
.addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
Map<String, Object> userHashMap = new HashMap<String, Object>();
userHashMap = documentSnapshot.getData();
User user = (User) userHashMap.get("userdata");
I also can't use:
User user = documentSnapshot.toObject(User.class);
So I wondered whether someone can suggest a way how to retrieve a custom object from a HashMap? I should also mention that the document will contain a second HashMap.

Categories