How to give user defined key value in push(), instead of unique value created by push?
This is what am currently doing:
User user = new User(Editname.getText().toString(),
Editpid.getText().toString(),Editsem.getText().toString());
mRef.child("users").push().setValue(user);
.push() will create a new item with a unique reference.
You can use updateChildren() to update instead. For example,
User user=new User(Editname.getText().toString(),Editpid.getText().toString(),Editsem.getText().toString());
Map<String, Object> itemValues = user.toMap();
Map<String, Object> childUpdates = new HashMap<>();
// Define the key value here
String username = "yourKeyValueHere";
childUpdates.put("/users/" + username, itemValues);
mDatabase.updateChildren(childUpdates);
You might have to add something similar to the following to your User class.
#Exclude
public Map<String, Object> toMap() {
HashMap<String, Object> result = new HashMap<>();
result.put("name", name);
result.put("pid", pid);
result.put("sem", sem);
return result;
}
Simplest way is to specify the child key with the child method:
User user = new User(Editname.getText().toString(),
Editpid.getText().toString(),Editsem.getText().toString());
mRef.child("users").child(user.pid).setValue(user);
Where I specify user.pid, you can use whatever unique key you use to identify the user (typically when using Firebase Authentication this would be user.getUid()).
This is one way to do it assuming we want to use the User's name as unique key:
User user = new User(Editname.getText().toString(),
Editpid.getText().toString(),Editsem.getText().toString());
String uniqueKey = user.getName();
//You could use something else for quick reference since two users can have the same name
mDatabaseReference.child("users").child(uniqueKey).push().setValue(user);
Related
When using firebase (or any database that aggregates data basing on ids) I nearly always have to keep track of a key of a given value. For example let's assume I have Location class with latitude and longitude fields. When I download if from firebase, besides its two fields, I also want to keep track of the key (node value generated with push() e.g. -K_esEYXNfMBNmgF3fO4) it was downloaded from so I may later update it, delete it etc. I see only two solutions:
Duplicate the data and add key value as another Location class field. That doesn't work nicely because I have to set the key value only after I executed push().
Create generic wrapper class that will keep key and object:
public class Key<T> {
private final String key;
private final T value;
public Key(String key, T value) {
this.value = value;
this.key = key;
}
public String key() {
return key;
}
public T value() {
return value;
}
}
I am using the second approach but it doesn't look really nice. I have this Key class basically throughout all my codebase and when using RxJava plenty of methods have a return type like this: Observable<Key<Location>> and that just looks ridiculous.
What you call ridiculous actually looks quite normal to me.
Alternatively you can include the key in the POJO and annotate it with #Exclude to exclude it from the serialization.
Follow up on #FrankvanPuffelen great answer, do what you want with the below pushkey
Read and Write Data on Android
private void writeNewPost(String userId, String username, String title, String body) {
// Create new post at /user-posts/$userid/$postid and at
// /posts/$postid simultaneously
String key = mDatabase.child("posts").push().getKey();
Post post = new Post(userId, username, title, body);
Map<String, Object> postValues = post.toMap();
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put("/posts/" + key, postValues);
childUpdates.put("/user-posts/" + userId + "/" + key, postValues);
mDatabase.updateChildren(childUpdates);
}
In my app , there is an activity which upon clicking the save button, 2 sets of data in 2 different places should be made by push(), Since in both places an unique id is needed.
I have followed the sample code in the Firebase guide and added the second push
String userId = auth.getCurrentUser().getUid().toString();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
DatabaseReference firstDatabaseRef = reference.child("first");
DatabaseReference secondDatabaseRef = reference.child("second").child(userId);
String key = firstDatabaseRef.child(userId).push().getKey();
First first = new First(firstAmount,key,firstName);
Map<String, Object> firstValues = first.toMap();
String keySecond = secondDatabaseRef.child(key).push().getKey();
Second second = new Second(secondName,secondAmount,keySecond,key);
Map<String, Object> secondValue = second.toMap();
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put("/first/" + userId + "/" + key, firstValues);
childUpdates.put("/second/" + userId + "/" + key + "/" + keySecond, secondValue);
reference.updateChildren(childUpdates);
The result that i got for first was exactly as i expected but for second , instead of creating second/<userId>/<key>/<keySecond>/children, i get this :
"second" : {
//userId
"5TQLPlGf4mbcBRKesQwR30fH1L22" : {
//key
"-KL1030IywlNpkTGC7mU" : {
"secondAmount" : "147",
"Key" : "-KL1030IywlNpkTGC7mU",
"secondName" : "secondName",
"keySecond" : "-KL1030PZlHqD_asSR_8",
}
}
}
Instead of having the final children in another unique id, which by the way is recorded in the keySecond, they are all added directly to the key.
This cannot be accepted since every key must have many keySecond.
I hope that i explained my problem correctly.
Please tell me what am i doing wrong.
How should i modify my code or should i reconsider my data structure completely ?
This is a puzzle. I copy/pasted the code you posted and created stubs for First and Second. Running with Firebase 9.0.2 produced the result shown below, which I believe is what you are expecting. Are you running with a different Firebase version? Is it possible the JSON you posted was produced by a different version of the code you posted?
{
"first" : {
// userId
"ypx8RB3eglTBRPeUT7laQVQ1PZQ2" : {
// key
"-KL3rXeYrscFQNrVQnHb" : {
"firstAmount" : "FirstAmount",
"firstKey" : "-KL3rXeYrscFQNrVQnHb",
"firstName" : "FirstName"
}
}
},
"second" : {
// userId
"ypx8RB3eglTBRPeUT7laQVQ1PZQ2" : {
// key
"-KL3rXeYrscFQNrVQnHb" : {
// keySecond
"-KL3rXe_JyY9Vz2U-NES" : {
"Key" : "-KL3rXeYrscFQNrVQnHb",
"keySecond" : "-KL3rXe_JyY9Vz2U-NES",
"secondAmount" : "SecondAmount",
"secondName" : "SecondName"
}
}
}
}
}
When processing the updateChildren(), the Firebase Database loops over the children that you pass and for each key it essentially does a setValue() with the value you passed.
That means that if you have children with overlapping keys, the value of one of those keys will be written last. The order of these is undefined.
In your case it's fairly easy to merge the updates together:
String key = firstDatabaseRef.child(userId).push().getKey();
First first = new First(firstAmount,key,firstName);
Map<String, Object> firstValues = first.toMap();
String keySecond = secondDatabaseRef.child(key).push().getKey();
Second second = new Second(secondName,secondAmount,keySecond,key);
Map<String, Object> secondValue = trans.toMap();
firstValues.put(keySecond, secondValue); // This is the main change
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put("/first/" + userId + "/" + key, firstValues);
reference.updateChildren(childUpdates);
I have two nodes from one root and I want to delete the data from both of them in one request. Both sub-nodes has the same key. I tried this:
Firebase firebaseRef = new Firebase(<root_path>);
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put(<path_to_first_node>, key);
childUpdates.put(<path_to_second_node>, key);
listToRemoveRef.updateChildren(childUpdates, null);
But it removed data from only the first node
It looks like you're using the updateChildren function wrong. What you want to do is this
Firebase firebaseRef = new Firebase(<root_path>);
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put("<path_to_first_node>" + key, null);
childUpdates.put("<path_to_second_node>" + key, null);
listToRemoveRef.updateChildren(childUpdates);
The second parameter to updateChildren doesn't set the value to null it is an optional completion listener (see documentation). So instead of passing null to it on the last line, you can just omit it.
This is my code for adding records in Firebase. there's variable outside called restauCount valued (int) as 1
public void sendMessage(){
int restauCount = 1;
String identifier ="Restaurant" + restauCount;
Firebase userRef = firebaseRef.child("Caloocan");
EditText nameInput = (EditText) findViewById(R.id.nameTxt);
String name = nameInput.getText().toString();
EditText locInput = (EditText) findViewById(R.id.locationTxt);
String location = locInput.getText().toString();
EditText typeInput = (EditText) findViewById(R.id.typeTxt);
String foodtype = typeInput.getText().toString();
if (!name.equals("")){
Map<String, String> caloocan = new HashMap<String, String>();
caloocan.put("resname", name);
caloocan.put("resloc", location);
caloocan.put("foodtype", foodtype);
Map<String, Map<String, String>> users = new HashMap<String, Map<String, String>>();
users.put(identifier,caloocan);
userRef.setValue(users);
restauCount++;
}
}
When i run the sendessage() again. i will type in the fields and when i click ADD which is the sendMessage it will be added in FireBase , however when i add new data. IT OVERWRITES THE OLD DATA INPUTTED ? HOW CAN I ADD MULTIPLE DATA IN FIREBASE WITHOUT OVERWRITING THE DATA?
restauCount was created to increment the number of Restaurant i inputted,
userRef.push().setValue(users);
The push() method generates a unique key every time a new child is added to the specified Firebase reference
Use
userRef.setValue(users).push();
instead of userRef.setValue(users);
You are using always the same ref
String identifier ="Restaurant" + restauCount;
Firebase userRef = firebaseRef.child("Caloocan");
userRef.setValue(users);
restauCount++;
Check the doc:
Using setValue() in this way overwrites data at the specified location, including any child nodes.
In your case you are overriding the same data for this reason.
You should use the push() method to generate a unique ID every time a new child is added to the specified Firebase reference.
Firebase userRef = firebaseRef.child("Caloocan");
Firebase newRef = userRef.push();
newRef.setValue(users);
//to get the key
String key = newRef.getKey();
you need to update the identifier it stays the same :
int restauCount = 1;
String identifier ="Restaurant" + restauCount;
try something like :
long restauCount = System.currentTimeMillis();
String identifier ="Restaurant" + restauCount;
here each time you send a sendMessage() your identifier got a specific id as the current time in milliseconds + "Restaurant"
if its important to keep int numbers let me know
I want to store three values in shared preference
Can I store integer as third value in hashmap? As i passed null for string, what can i passed for integer?
public HashMap<String, String> getUserDetails(){
HashMap<String, String> user = new HashMap<String, String>();
// user name
user.put(KEY_NAME, pref.getString(KEY_NAME, null));
// user email id
user.put(KEY_PASS, pref.getString(KEY_PASS, null));
user.put(KEY_ID,pref.getInt(KEY_ID,));//what should i pass here??
// return user
return user;
}
you've declared your HashMap() as a map that contains String objects, so, no, you can't really just store an integer in there. However, you can convert the integer to a string if you like. Since getInt() returns a primitive int, you should use the static method Integer.toString(valuetomakeintoastring)
The second value in your call to getInt() is the default value that should be returned if the KEY value is not found in the preferences. Use some value that can't be confused as a valid value for your application.
user.put(KEY_ID,Integer.toString(pref.getInt(KEY_ID,<somedefaultintegervalue>));
Perhaps a HashMap is not the right data structure for you to use here? Perhaps you really need to define a class that contains these values together, then create a HashMap of that class?