7

Can I create relationships between my object stores in IndexedDB?

For example, I have two object stores: artist and album. An artist has a one-to-many relationship with an album. album.artistId relates the album to artist.id.

I'm thinking along the lines of Hibernate here. I would like to do a query for artists and have the albums belonging to that artist returned as an array called artists on the album object.

artist.albums = [];

Follow Up (4.5 years later, 2017)

There are some great answers below that answer the question very well. I'd like to add that I was originally trying to use IndexedDB as a relational store and build an ORM-like solution on top of it, which it is not suited for. IndexedDB is a NoSQL database and since I've started treating it that way it's made more sense and my projects easier to manage. I hope this adds some value to the original question for those who continually come across it.

Josh Johnson
  • 10,729
  • 12
  • 60
  • 83

4 Answers4

4

In IndexedDB, relationship is just reference to other store. In this case, artist store's id is indexed field, artistId, in album store. In this way, you can quickly query using key range query.

Using ydn.db.Storage database wrapper,

var schema = [stores: [
  {name: 'artist'},
  {name: 'album', 
    indexes: [
      {name: 'artistId'}
    ]
  }
];  
db = new ydn.db.Storage('dbname', schema)

suppose, we are interst in artist, aid.

db.get('artist', aid).success(function(artist ) {     
  db.query('album', 'artistId').only(aid).success(function(albums) {
    // display artist and albums
  })    
});
Kyaw Tun
  • 12,447
  • 10
  • 56
  • 83
  • Is this possible to run on a single query? Like, `db.get('artist', 'album').success( function (result) { // result is (object)artist and (array)artist.albums });` – paolooo Feb 26 '14 at 08:59
  • No, unless compound index for parents child relationship is used. – Kyaw Tun Feb 26 '14 at 10:03
2

The indexedDB provides low level methods to create, read, update, and delete (CRUD) "records" of objects. But the standard does not define specific methods for relational operations. The goal was to keep the standard simple and allow developers to implement the higher-level functions in any way they saw fit. However, what you're asking for is still attainable through a small amount of development on your part.

To help things out, Parashuram Narasimhan wrote a Jquery implementation for indexedDB that will finish the job for you.

Jquery indexedDB Example 1

Jquery indexedDB Example 2

Consider the following generalized possibility:

$.indexeddb("MyDatabase")
  .objectStore("Artist")
  .openCursor()
  .each(function(){
    //Got Artist
    //Enumerate for Albums
    $.indexeddb("MyDatabase")
      .objectStore("Artist")
      .openCursor()
      .each(function(){
        //Check for matching artist.Id
        //if this albums's artist matches artist
        //then do something
        }
      ;
    }
  ;

A little late for an answer, but I hope it helps grease the gears a bit.

1

You could also try using LINQ2IndexedDB - another library that uses LINQ style queries for IndexedDB - http://linq2indexeddb.codeplex.com

axemclion
  • 61
  • 2
0

I see two ways to approach this problem.

The first would be to go third normal form-style -- have one object store to store data objects, and another to store the relationships between them. IndexedDB doesn't support the concept of JOIN so you'll have to do two database hits anyways, and with that approach the two stores can each can have separate indexes (which are key, so to speak).

Stepping back a bit, depending on your need you might be able to just store your whole JS object using a simple key/value approach. I haven't measured anything, but my instinct so far is that if you're not dealing with medium amounts of data you don't need to deal with the complexities of normalization.

Stepping back even further, if you don't really indexes than you might not really need IndexedDB. If you're just looking for local store, try localStorage. It's very compatible with modern browsers and the API is way simpler.

var obj = { data_object_1: { 'incoming': [ 1, 2, 3 ], 'outgoing': [ 5, 6, 7 ] } };
localStorage.setItem( 'foobar', JSON.stringify( obj ) );
console.log( JSON.parse( getItem( 'foobar' ) ) );
buley
  • 28,032
  • 17
  • 85
  • 106
  • Another key benefit of indexedDB is that all operations are done in transactions – Wex Oct 08 '21 at 12:32