Search code examples
gun

How do I delete data in gun DB when path has multiple objects


How do I delete data when my path contains multiple objects? gun.path('saving_accounts').put(null) would delete all savings accounts. Or, do you have a way to handle the null errors when iterating over data that has a 'deleted' object? I'm providing fully working examples to try to help in answering. Say I create gun data with this:

// localStorage.clear();
var gun = Gun();

////////////////////////////////////////////////////////////////// create record

var saving1 = gun.put({
    name: "Bank of America",
    accType: "Saving",
    last4: "5555",
    favorite: true,
    status: true,
    created: "some date created"
  });

var saving2 = gun.put({
    name: "Bank of America",
    accType: "Saving",
    last4: "4123",
    favorite: true,
    status: true,
    created: "some date created"
  });

var saving_accounts = gun.get('saving_accounts')
saving_accounts.set(saving1);
saving_accounts.set(saving2);

Then i can query all savings accounts with something like this:

const queryMultiple = (data_path) => {
  console.log("Query for: " + data_path);
  gun.get(data_path).map().val((name, ID) => {
    // console.log(ID);
    console.log(name.name, name.accType, ID);
  });
};
queryMultiple('saving_accounts');

I tried to delete a record based on the gundb question here and wiki gun.path('object3').put(null) but I'm not sure how to change it for my application. On the savings account path, there are multiple savings accounts. So if i want to delete a specific savings account, i delete it by id but I think i'm doing it wrong. Say the id of the account i want to delete is FesxPaup8gzuNSsLFlWXMKaL:

// delete record
const deletebyID = (data_path, qID) => {
    console.log("DELETE record");
    gun.get(data_path).path(qID).put(null);
};

deletebyID('saving_accounts', 'FesxPaup8gzuNSsLFlWXMKaL');

But the .put(null) above will make the object FesxPaup8gzuNSsLFlWXMKaL point to null and when i list all savings accounts again with queryMultiple('saving_accounts'); I get a cannot read property name of null.

How do I delete data when my path contains multiple objects?

Side note: eventually i will nest multi transactions for a savings account under each savings account so I will have to do the same thing when deleting a account transaction that was made by mistake. Also hopefully when i delete a savings account, it automatically deletes/nulls all of that accounts transactions too but i haven't gotten past playing playing with data at this first layer.


Solution

  • @jtlindsey great question! You are correct though on how to delete data, even about how to delete an item inside a list/collection/table. But here is how to get the results you want:

    Quick Solution:

    Change your query to this:

    const queryMultiple = (data_path) => {
      console.log("Query for: " + data_path);
      gun.get(data_path).map().val((name, ID) => {
        if(!name){ return }
        // console.log(ID);
        console.log(name.name, name.accType, ID);
      });
    };
    queryMultiple('saving_accounts');
    

    And it will work. Why? Because it filters out any nulled account.

    Why All the Nulls?

    Deletes in GUN work like Mac OSX or Windows or Linux. The nulling tells every machine to "Put this data in the trash/recycle bin". The reason this is useful is because it lets you change your mind about deleting something, so you can recover it later if you want. (Recovering deleted content/files happens a LOT, but it something most people don't think about).

    The null data also is useful for notifications! This is very applicable when you are designing frontend websites and you are rendering HTML. Let's go over a simple example:

    Example

    Imagine your user is checking the site on his phone, and realizes he needs to get clear up some issues that are a little bit more complicated so he logs on with his laptop. After checking the details on the laptop he decides to delete the account. Underneath his "click" action causes your run code to run:

    // delete record
    const deletebyID = (data_path, qID) => {
        console.log("DELETE record");
        gun.get(data_path).path(qID).put(null);
    };
    
    deletebyID('saving_accounts', 'FesxPaup8gzuNSsLFlWXMKaL');
    

    Which is correct. However, if he then closes his laptop and picks his phone back up... he'll notice his account is still there!!! Which is not a good experience. But with GUN fixing this is easy because of the null notification:

    gun.get(data_path).map().on((account, ID) => {
      var UI = $("#account-" + ID);
      if(!account){
        UI.remove();
        return;
      }
      updateUI(ID, account);
    });
    

    Now when they pick up their phone it will reflect the current state of their accounts! They'll see that it had been removed on all their devices because the null got synced to all devices.


    Does that make sense? Does that your answer your question? Need help with anything else? As always, https://gitter.im/amark/gun and https://github.com/amark/gun/wiki/delete and http://gun.js.org/ .