Rasmus Rajje Josefsson Rasmus Rajje Josefsson - 6 months ago 45
JSON Question

Firebase Moving one item to another node

What If I want to move one item from the "Private" node, like this one:

"2016-06-01 23:40:08"
to the location of the "Work" node with the correct year and month node. Do I use the onChildMoved() to move it and how do I really get it into the right nodes

JSON

{
"users" : {
"S1PtLPZ1mISXsbwpbz1NoLclpAV2" : {
"email" : "kalle@hotmail.se"
},
"aBZtC3VjpPc8o40AjA9sGZg0TC23" : {
"email" : "skola@hotmail.com",
"waypoints" : {
"Private" : {
"2016" : {
"06" : {
"2016-06-01 23:40:08" : {
"destination" : "Västerlånggatan 10, 451 31 Uddevalla, Sweden",
"distance" : "8.9 m",
"duration" : "1 min",
"encodedLatLngs" : "{sccJaoygA?]",
"origin" : "Västerlånggatan 10, 451 31 Uddevalla, Sweden",
"timeStamp" : "2016-06-01 23:40:08",
},
"2016-06-01 23:40:51" : {
"destination" : "Västerlånggatan 8, 451 31 Uddevalla, Sweden",
"distance" : "34.7 m",
"duration" : "1 min",
"encodedLatLngs" : "yoccJsoygA}@B",
"origin" : "Västerlånggatan 4, 451 50 Uddevalla, Sweden",
"timeStamp" : "2016-06-01 23:40:51",
}
}
}
},
"Work" : {
"2016" : {
"06" : {
"2016-03-01 21:40:08" : {


Demo

FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
// User is signed in
String mUserId = user.getUid();

final String mTravelType = "Private";
final String year = "2016";
final String month = "06";
final String key = "2016-06-01 23:40:08";


String waypointsUrl = Constants.FIREBASE_URL_MAIN_REF + "/users/" + mUserId + "/waypoints";
mWaypointRef = FirebaseDatabase.getInstance().getReferenceFromUrl(waypointsUrl);



// NEW VALUES
mDateRef = mWaypointRef.child("Work").child(year).child(month).child(key);
final String newValues = mDateRef.toString();
Log.i("path to new values", newValues);
// https://rjcar3.firebaseio.com/users/waypoints/Work/2016/06


// OLD VALUES
mDateRef = mWaypointRef.child(mTravelType).child(year).child(month).child(key);
final String oldValues = mDateRef.toString();
Log.i("path to old values", oldValues);
//https://rjcar3.firebaseio.com/users/waypoints/Private/2016/06/



mDateRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {

// MyClass is your POJO Class (class representing the node with it's children)
// https://firebase.google.com/docs/database/android/save-data#update_specific_fields
MyWaypoint node = dataSnapshot.getValue(MyWaypoint.class);
Log.i("Node", node.toString());


//Because the key is not a child you need to set it manually
node.setKey(dataSnapshot.getKey());


//You need to create a toMap() method for your class in order to save the values to the new location
Map<String, Object> nodeValues = node.toMap();

Log.i("nodeValues", nodeValues.values() + "");
Log.i("nodesSize", nodeValues.size() + "");

//Here you create the updates you want to execute
Map<String, Object> childUpdates = new HashMap<>();
//Save in the new location
//The path should be from waypoints to the key ex: "Work/2016/06/2016-06-1 23:40:08"
childUpdates.put(newValues + node.getKey(), nodeValues);


for (Object item : childUpdates.values()){
Log.i("loop",item.toString());
}

for (Object item : nodeValues.values()){
Log.i("looop",item.toString());

}

//Erase the old location
//The path should be from waypoints to the key ex: "Private/2016/06/2016-06-1 23:40:08"
childUpdates.put(oldValues + node.getKey(), null);

mWaypointRef.updateChildren(childUpdates);
}

@Override
public void onCancelled(DatabaseError databaseError) {

}
});
}


CatLog

06-02 19:51:47.555 6872-6872/com.example.rasmusjosefsson.rjcar I/path to old values: https://rjcar3.firebaseio.com/users/aBZtC3VjpPc8o40AjA9sGZg0TC23/waypoints/Private/2016/06
06-02 19:51:47.555 6872-6872/com.example.rasmusjosefsson.rjcar I/path to new values: https://rjcar3.firebaseio.com/users/aBZtC3VjpPc8o40AjA9sGZg0TC23/waypoints/Work/2016/06
06-02 19:51:47.577 6872-6872/com.example.rasmusjosefsson.rjcar I/Node: com.example.rasmusjosefsson.rjcar.POJO_Firebase.MyWaypoint@286ef13
06-02 19:51:47.578 6872-6872/com.example.rasmusjosefsson.rjcar I/nodeValues: [null, null, null, null, null, null, null]
06-02 19:51:47.578 6872-6872/com.example.rasmusjosefsson.rjcar I/mWaypointRef: https://rjcar3.firebaseio.com/users/aBZtC3VjpPc8o40AjA9sGZg0TC23/waypoints
06-02 19:51:47.761 6872-7027/com.example.rasmusjosefsson.rjcar W/RepoOperation: updateChildren at /users/aBZtC3VjpPc8o40AjA9sGZg0TC23/waypoints failed: DatabaseError: Invalid token in path


POJO Class

@IgnoreExtraProperties
public class MyWaypoint {

private String encodedLatLngs;
private String duration;
private String destination;
private String distance;
private String origin;
private String timeStamp;
private String key;

public MyWaypoint() {
}


public MyWaypoint(String timeStamp, String origin, String destination, String duration, String distance, String encodedLatLngs, String key) {
this.timeStamp = timeStamp;
this.origin = origin;
this.destination = destination;
this.duration = duration;
this.distance = distance;
this.encodedLatLngs = encodedLatLngs;
this.key = key;
}


@Exclude
public Map<String, Object> toMap() {
HashMap<String, Object> result = new HashMap<>();
result.put("key", key);
result.put("destination", destination);
result.put("distance", distance);
result.put("duration", duration);
result.put("origin", origin);
result.put("timeStamp", timeStamp);
result.put("encodedLatLngs", encodedLatLngs);
return result;
}


public void setKey(String key){
this.key = key;
}

public String getKey(){
return this.key;
}

public String getDistance() {
return distance;
}

public void setDistance(String distance) {
this.distance = distance;
}


public String getEncodedLatLngs() {
return encodedLatLngs;
}

public void setEncodedLatLngs(String encodedLatLngs) {
this.encodedLatLngs = encodedLatLngs;
}


public String getDestination() {
return destination;
}

public void setDestination(String destination) {
this.destination = destination;
}


public void setDuration(String duration) {
this.duration = duration;
}

public String getDuration() {
return duration;
}


public String getOrigin() {
return origin;
}

public void setOrigin(String origin) {
this.origin = origin;
}

public String getTimeStamp() {
return timeStamp;
}
public void setTimeStamp(String timeStamp) {
this.timeStamp = timeStamp;
}
}

Answer

Ok i've checked your code and changed it, just edit my default strings and it should work Hope it helps...

The errors were: 1) The path was adding an extra key date 2) In the toMap() we were adding an extra key

ok Here is the main Activity

    public class MainActivity extends AppCompatActivity {
    private DatabaseReference waypointRef;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        String mTravelType = "Private";
        final String year = "2016";
        final String month = "06";
        final String dateKey = "2016-06-01 23:40:08";
        String mUserId = user.getUid();

        FirebaseDatabase database = FirebaseDatabase.getInstance();
        DatabaseReference myRef = database.getReference("users");

        waypointRef = myRef.child(mUserId).child("waypoints");
        Log.e("ref",waypointRef.toString());

        waypointRef.child(mTravelType).child(year).child(month).child(dateKey).addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                Log.e("data",dataSnapshot.toString());

                MyClass node = dataSnapshot.getValue(MyClass.class);
                node.setKey(dataSnapshot.getKey());

                Map<String, Object> nodeValues = node.toMap();

                Map<String, Object> childUpdates = new HashMap<>();

                String work_path = "/Work/" + year + "/" + month + "/" + "/" + dateKey + "/";
                String private_path = "/Private/" + year + "/" + month + "/" + dateKey + "/";

                childUpdates.put(work_path, nodeValues);
                childUpdates.put(private_path, null);

                waypointRef.updateChildren(childUpdates);

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });

    }
}

And here is the Class

@IgnoreExtraProperties
public class MyClass {
    private String key;
    private String destination, distance;

    public MyClass() {
    }

    @Exclude
    public String getKey() {
        return key;
    }

    @Exclude
    public void setKey(String key) {
        this.key = key;
    }

    public String getDestination() {
        return destination;
    }

    public void setDestination(String destination) {
        this.destination = destination;
    }

    public String getDistance() {
        return distance;
    }

    public void setDistance(String distance) {
        this.distance = distance;
    }

    @Exclude
    public Map<String, Object> toMap() {
        HashMap<String, Object> result = new HashMap<>();
        result.put("destination", destination);
        result.put("distance", distance);

        return result;
    }

}
Comments