I am trying to add the HashMap "attending" to the .collection("Users").document(user_id) and it seems that .add() does not work with this, so I used .set(), however it erases all the previously stored data on the document(user_id).
How could I just add the fields to the document rather then rewriting the whole document in this case?
attending.put(ID,a);
firebaseFirestore.collection("Events").document(ID).collection("Users").add(userMap).addOnCompleteListener(new OnCompleteListener<DocumentReference>() {
#Override
public void onComplete(#NonNull Task<DocumentReference> task) {
//Toast.makeText(eventRegistration.this, "User Stores", Toast.LENGTH_SHORT).show();
}
});
firebaseFirestore.collection("Users").document(user_id).set(attending).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Toast.makeText(eventRegistration.this, "Registered Successfully", Toast.LENGTH_SHORT).show();
}
});
Using add() on a CollectionReference. always creates a new document with a random ID. Calling set() on a DocumentReference will overwrite the document, but you can change that by passing a second SetOptions type argument that says to merge the new data with the existing data - just call SetOptions.merge() to get that object to pass. update() will always just try to update an existing document.
The fact that you're trying to update with a Map doesn't change the way any of these methods work.
All of these operations are also discussed in the documentation.
Related
I have two collections in my firestore database, the first is list of all the documents (BlockList), and the second for the users. when the user bookmark post on Recyclerview on the app, send the id of the document and timestamp to sub-collection (Favorites) under Users Collection.
i retrieve the list of documents based on this ids from the main collection (BlockList), but i want to arrange them according to timestamp for each user, so i've tried to order them by timestamp before adding them to Arraylist and Log the list, i've got the correct result. but the recyclerview still retrieved them ascending order by document ID !
firebaseFirestore.collection("Users")
.document(userId).collection("Favorites").orderBy("timestamp", Query.Direction.DESCENDING).get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
List<String> list = new ArrayList<>();
for (QueryDocumentSnapshot document : task.getResult()) {
list.add(document.getId());
}
Log.d(TAG, list.toString());
if (list.size() != 0){
blockReffav = firebaseFirestore.collection("BlockList")
.whereIn(FieldPath.documentId(), list);
blockReffav.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if(task.isSuccessful()){
onFirestoreTaskComplete.blockListDataAdded(task.getResult().toObjects(BlockListModel.class));
} else {
onFirestoreTaskComplete.onError(task.getException());
}
}
});
}
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
}
});
Given how you currently retrieve the documents:
blockReffav = firebaseFirestore.collection("BlockList")
.whereIn(FieldPath.documentId(), list);
There is no way to specify the order of the IDs in the list in this query, so you will get them back in (the default) order of document IDs.
I see two options:
Request the documents one by one, so that you get them in the correct order.
Re-order the documents in your application code to match the order in the list.
I'd recommend the latter, as it's likely to be both simpler and more reliable.
I am building an app using Firebase where I am checking for presence of certain values in the node and if it is present I am just adding to it instead of creating a new node.
But when I try to implement the same its actually implementing infinite query and database getting filled up
For simplicity I am including that portion of the code that is causing problem:
Here the else coode means as the data node is already present in the database I am appending.
else {
user u=new user(SharedPrefManager.getmInstnce(ChatList.this).getUsername(),SharedPrefManager.getmInstnce(ChatList.this).getmail());
for(int l=0;l<grpar.size();l++){
if(grpar.get(l).getName().equalsIgnoreCase(grpname)){
index=l;
break;
}
}
Log.i("Checking QUERY","Value exist!!!! in "+ index);
grpar.get(index).getGrpMembers().add(u);
Group grp=new Group(grpname,grpar.get(index).getGrpMembers());
grpRef.push().setValue(grp).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful())
{
Intent intent = new Intent(ChatList.this,MainActivity.class);
intent.putExtra("Id","none");
intent.putExtra("Name",grpname);
startActivity(intent);
}
else
{
Toast.makeText(ChatList.this,"Data Not Added Completely",Toast.LENGTH_SHORT).show();
}
}
});
}
From the moment I applied the following logic it started behaving abnormally:
for(int l=0;l<grpar.size();l++){
if(grpar.get(l).getName().equalsIgnoreCase(grpname)){
index=l;
break;
}
}
I am also attaching the DB structure:
I cannot figure out where the error is ! Any help is appreciated
I have multiple buttons in my android application and when clicked it has to fetch data from Firebase database and the fetched data is added into a list which has to be passed as an argument to another class constructor . But the fetching of data happens in another thread by default since firebase queries are asynchronous . How do I make sure that list has been added with data from other thread before passing it to constructor ?
It's simple use oncompletelistener you can refer this example:
db=FirebaseFirestore.getInstance();
db.collection("Order").document(TableListFragment.tableno)
.update(
"Items", FieldValue.arrayUnion("ABCD"),
"Quantity", FieldValue.arrayUnion("34")
).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Toast.makeText(getContext(),"Item Added",Toast.LENGTH_LONG).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.i("onFailure:",e.toString());
}
});
I have one node name users which is populating fine, but I am trying to incorporate a new node events, which I am having trouble with. I have copied exactly what works in the users, but I am clearly doing something wrong. It never goes into the OnCompleteListener. Is there something I am missing?
R.string.dbnode_events ="events"
Events events = new Events();
events.setEvent_key(mEventKey);
events.setEvent_title("");
events.setEvent_date("");
events.setEvent_time("");
events.setEvent_millis("");
events.setEvent_desc("");
events.setEvent_filter("");
events.setGroup_number("");
FirebaseDatabase.getInstance().getReference()
.child(getString(R.string.dbnode_events))
.child(mEventKey)
.setValue(events).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Toast.makeText(CreateEventActivity.this, "Success", Toast.LENGTH_SHORT);
}
});
More Information/ Example: The top user one creates a node no problem but the events one has yet to create. I hope this might give some more insight.
User user = new User();
user.setName(email.substring(0, email.indexOf("#")));
user.setPhone("1");
user.setProfile_image("");
user.setSecurity_level("1");
user.setUser_id(FirebaseAuth.getInstance().getCurrentUser().getUid());
user.setEmail(FirebaseAuth.getInstance().getCurrentUser().getEmail());
user.setStreet_address("");
user.setCity("");
user.setState("");
user.setZip("");
user.setMember_filter("Member");
user.setSmall_group_subscription1("");
user.setSmall_group_subscription2("");
user.setSmall_group_subscription3("");
user.setSmall_group_subscription4("");
user.setSmall_group_subscription5("");
user.setShow_phone("No");
user.setShow_email("Yes");
user.setShow_address("No");
FirebaseDatabase.getInstance().getReference()
.child(getString(R.string.dbnode_users))
.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
.setValue(user)
.addOnCompleteListener(task1 -> {
FirebaseAuth.getInstance().signOut();
redirectLoginScreen();
}).addOnFailureListener(e -> {
FirebaseAuth.getInstance().signOut();
redirectLoginScreen();
Toast.makeText(RegisterActivity.this, "Database Problem ",Toast.LENGTH_SHORT);
});
/////////////////////////
String mEventKey = UUID.randomUUID().toString();
Events events = new Events();
events.setEvent_key(mEventKey);
events.setEvent_title("");
events.setEvent_date("");
events.setEvent_time("");
events.setEvent_millis("");
events.setEvent_desc("");
events.setEvent_filter("");
events.setGroup_number("");
FirebaseDatabase.getInstance().getReference()
.child(getString(R.string.dbnode_events))
.child(mEventKey)
.setValue(events)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Toast.makeText(RegisterActivity.this, "Success", Toast.LENGTH_SHORT);
}
});
This is what i have done, probably it will help :D
When you add a class, you have to create a reference like this :
private DatabaseReference Accounts;
And inside the onCreate :
Accounts = FirebaseDatabase.getInstance().getReference("Accounts");
After that, set ur class. I do this for the user :
currentwithID = new Class_user(uID,uSer,matchFound);
And than set it on the node :
uID is the token given by Google
Accounts.child(uID).setValue(currentwithID);
I have done the same things to every node of my database, and it perfectly works.
Try to do that with this code, and tell me if it works :D
I want to use custom function in my android application for sign up in firebase. Currently I am using the createUserWithEmailAndPassword function. It takes two parameters by default i.e Email & Password but my sign up form includes other attributes also like, phone number, name etc. So what should I do? Currently I am using the below code.
firebaseAuth.createUserWithEmailAndPassword(Email,Password).addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if(task.isSuccessful())
{
progressDialog.cancel();
Toast.makeText(SignUp.this,"Registration Successful",Toast.LENGTH_SHORT).show();
}
else
{
progressDialog.cancel();
Toast.makeText(SignUp.this,"Could Not Register. Try Again.",Toast.LENGTH_SHORT).show();
}
}
});
Thank You :)