Add an item to a list in Firebase Database

前端 未结 4 1997
礼貌的吻别
礼貌的吻别 2021-01-01 16:14

I have the following Firebase database structure. uIds is a type of List. I am trying to add another uId under uIds with

相关标签:
4条回答
  • 2021-01-01 16:46

    The Firebase documentation on creating data that scales proposes that you use a different data structure:

    "requests" : {
      "-KSVYZwUQPfyosiyRVdr" : {
        "interests" : { "x": true },
        "live" : true,
        "uIds" : { 
          "user1": true, 
          "user2": true 
        }
      },
      "-KSl1L60g0tW5voyv0VU" : {
        "interests" : { "y": true },
        "live" : true,
        "uIds" : { 
          "user2": true 
        }
      }
    }
    

    Here are a few of the reasons why this data structure works better:

    • each uid can now automatically only appear once. We've essentially modeled our data as a set, instead of using an array.
    • adding an item is now as easy as ref.child("uUids").child("user3").setValue(true)
    • you can now check if a uid exists in your security rules.

    I have started re-iterating to myself: whenever you find yourself doing array.contains("xyz"), you should probably be using a set instead of an array. The above mapping with "key": true is an implementation of a set on Firebase.

    Efficiency

    Some people may think arrays are a more efficient way of storing the data, but in the case of Firebase that is not true:

    What you see:

    "uIds" : [ "user1", "user2" ]
    

    What Firebase stores:

    "uIds" : {
      "0": "user1",
      "1": "user2"
    }
    

    So storing a set is pretty much the same:

    "uIds" : { 
      "user1": true, 
      "user2": true 
    }
    
    0 讨论(0)
  • 2021-01-01 16:55

    Adding 2 cents to Frank van Puffelen answer, you can use the key from push operation as a unique identifier of your request. Plus if you use hash map to update child then your DB will not be overridden

     // Create a node on Server and get key
      String requestID = AdminController.getInstance().referenceFromUrl
                            .child(END_POINT_REQUESTS)
                            .push().getKey();
    
      //use key as ID for your Object which you want to push as unique identifier of your model
      requestToPush.setRequestId(requestID );
    
     //Add updated Model Object in a Map to update DB instead of over writing
     requestsMap.put(requestID , requestToPush);
    
     //Update newly created DB nodes with data
       referenceFromUrl
                .child(END_POINT_REQUESTS)
                .updateChildren(productsMap,
                        new DatabaseReference.CompletionListener() {
                            @Override
                            public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
    
                                if (databaseError != null) {
                                    Log.e(TAG, "Error: Data could not be saved "
                                            + databaseError.getMessage());
                                } else {
                                    Log.e(TAG, "Success : Data saved successfully.");
                                }
                            }
                        });
    

    Result

    0 讨论(0)
  • 2021-01-01 16:58

    There is a good old article from the Firebase official blog explaining why we should avoid array in our database : Arrays are Evil

    So it's not possible to modify an array without replacing the array. I suggest to change your database structure to this

    "requests" : {
        "<pushKey1>" : {
            "interests" : [ "x" ],
            "live" : true,
            "uIds" : {
                "<pushKey1>" : "user1",
                "<pushKey2>" : "user2"
            }
        },
        "<pushKey2>" : {
            "interests" : [ "y" ],
            "live" : true,
            "uIds" : {
                "<pushKey1>" : "user2"
            }
        }
    }
    

    To get the pushKey, you can use push() method (the same as what you have done to each Request item)

    Then the code will be like this if you just want to add a new uid to a request.

    String requestKey = "request001";
    mDatabase.child("requests").child(requestKey).child("uIds").push().setValue("user2");
    

    Comment here if you have questions, hope this helps :)

    0 讨论(0)
  • 2021-01-01 17:10

    Not sure what you mean when you say setValue, etc require you to retrieve existing data. The basic flow for inserting new record is as follows:

    private DatabaseReference mDatabase;
    // get reference to your Firebase Database.
    mDatabase = FirebaseDatabase.getInstance().getReference();
    //and here you add a new child to your 'requests' collection
    //I am assuming you have a Request model like this..
    Request newRequest = new Request(some-params);
    mDatabase.child("requests").child(someRequestId).setValue(newRequest);
    

    You can take a look at basic usage guide for Saving Data on Android Firebase.

    Update: Following your comment - I think what you are looking to do can be achieved like this: You use the push() method which generates a unique ID every time a new child is added to the specified Firebase reference:

    Firebase newRequestRef = mDatabase.child("request").push();
    newRequestRef.setValue(newRequest);
    

    This should do it.

    I hope this helps.

    0 讨论(0)
提交回复
热议问题