taffydb

Querying TAFFYDB nested records


I have created a data model using TAFFYDB. Some of the fields have nested records. I am facing difficulties querying and updating the nested records.

For example:

var friends = TAFFY([
      {
        "id":1,
        "gender":"M",
        "first":"John",
        "last":"Smith",
        "city":"Seattle, WA",
        "comp": 
        [
          {
            "id":1,
            "audience":"cavern"
          },
          {
            "id":2,
            "audience":"cottage"
          }
        ]
      },
      {
        "id":2,
        "gender":"F",
        "first":"Basic",
        "last":"Smith",
        "city":"Seattle, WA",
        "comp": 
        [
          {
            "id":1,
            "audience":"bush"
          },
          {
            "id":2,
            "audience":"swamp"
          }
        ]
      }

    ]);

Supposing I need to update any of the comp field's audience, how will I go about it?


Solution

  • With regards to queries:

    When you have simpler nested arrays, you should be able to select specific records using the has and hasAll methods. However, there is an open issue that states neither of these methods work correctly. There are commits but since the issue has been left open, I assume they are not 100% fixed.

    For for complex nested data, like your example, the only thing I found was this old mailing list conversation talking about some sort of find method. No such method seems to exist though nor is there any mention of it in the docs.

    With regards to updates:

    You should be able to update the "comp" data by passing in the modified JSON that goes with it (assuming you are able to get the data out of the db in the first place) into a normal update. However, there is an open bug showing that update does not work when record values are objects. So even if you were able to query the data and were able to modify it, you wouldn't be able to update a record anyway because of the bug. You can however do a remove and an insert.


    Despite what I found above, I did some testing and found that you can update files by passing in objects. So this is a quick example of how to do a simple update:

    // To show what TAFFYDB looks like:
    console.log(friends().stringify());
    

    "[{"id":1,"gender":"M","first":"John","last":"Smith","city":"Seattle, WA","comp":[{"id":1,"audience":"cavern"},{"id":2,"audience":"cottage"}],"___id":"T000003R000002","___s":true},{"id":2,"gender":"F","first":"Basic","last":"Smith","city":"Seattle, WA","comp":[{"id":1,"audience":"bush"},{"id":2,"audience":"swamp"}],"___id":"T000003R000003","___s":true}]"

    // Get a copy of the comp file from the database for what you want to modify.
    // In this example, let's get the **first** record matching people with the name "John Smith":
    var johnsComp = friends({first:"John",last:"Smith"}).first().comp;
    // Remember, if you want to use select("comp") instead, this will return an array of results.
    // So to get the first result, you would need to do this despite there being only one matching result:
    // friends({first:"John",last:"Smith"}).select("comp")[0];
    
    // There are no nested queries in TAFFYDB so you need to work with the resulting object as if it were normal javascript.
    // You should know the structure and you can either modify things directly, iterate through it, or whatever.
    // In this example, I'm just going to change one of the audience values directly:
    johnsComp[0].audience = "plains";
    
    // Now let's update that record with the newly modified object.
    // Note - if there are more than one "John Smith"s, then all of them will be updated.
    friends({first:"John",last:"Smith"}).update({comp:johnsComp});
    
    // To show what TAFFYDB looks like after updating:
    console.log(friends().stringify());
    

    "[{"id":1,"gender":"M","first":"John","last":"Smith","city":"Seattle, WA","comp":[{"id":1,"audience":"plains"},{"id":2,"audience":"cottage"}],"___id":"T000003R000002","___s":true},{"id":2,"gender":"F","first":"Basic","last":"Smith","city":"Seattle, WA","comp":[{"id":1,"audience":"bush"},{"id":2,"audience":"swamp"}],"___id":"T000003R000003","___s":true}]"

    For a better targeted query or update (something that perhaps acts like a nested query/update), you can possibly try passing in a function. If you look at the docs, there is a simple example of this for update():

    db().update(function () {this.column = "value";return this;}); // sets column to "value" for all matching records