RE: [indexeddb] Compound Key support for Primary Keys and Indexes

Thanks for the feedback.  Answers inline.

Israel

On Tuesday, August 30, 2011 9:10 AM, Hans Wennborg wrote:
> On Sat, Aug 27, 2011 at 1:00 AM, Israel Hilerio <israelh@microsoft.com>
> wrote:
> > We looked at the spec to see what it would take to be able to support
> multi-column keys on primary keys & indexes and we found some
> inconsistencies that need to be addressed.  Below is our
> proposal/assumptions on how to constrain the problem and what needs to
> be updated in the spec to support this:
> >
> > . Cursors are automatically sorted in ascending order but they can be
> retrieved in descending order depending on the value passed to the
> IDBObjectStore.createIndex.  In other words, all of the attributes that make
> up the index or the primary key will share the same direction.  The default
> direction will match the single index case.
> 
> I'm not sure I'm following. What does "The default direction will match the
> single index case."? And how does the parameters passed to
> IDBObjectStore.createIndex affect the direction of cursors?

The concern is that compound indexes or keys could have conflicting sorting directions.  For example imagine the following list:

FirstName1, LastName10
FirstName2, LastName9
FirstName3, LastName8
FirstName4, LastName7

In this case, property1 is FirstName and property2 is LastName.  If we were to sort using the property1 you will get a different ordered list than if we were to sort using property2.  We're suggesting that we use the first property in the compound index or key to define the default sort.

> 
> >
> > . KeyRanges will act on the first element of the compound key (i.e. the first
> column).
> 
> Why? Compound keys are just another key type; shouldn't one be able to
> specify a KeyRange with compound keys as lower and upper and expect it to
> work as with other keys?
> 

You are correct!  The concern was the complexity this would introduce into the KeyRange mechanism.  In other words, defining the flexibility for a keyRange to be defined and allow each property to be individually parameterized could lead to situations in which one property in compound index can be defined to be ascending while another property could be defined to be descending.  That is the reason we were trying to scope the behavior to the first property in the compound index or key.

> >
> > . IDBObjectStore.get and IDBIndex.get will be able to take in an array
> > value.  Each value in the array will be mapped against the compound
> > key defined in the IDBObjectStore and the record will be queried using
> > all of the compound key values specified in the array.  Ifusing an
> > IDBKeyRange, the range will only be able to act on the first element
> > of the compound key.  Because the current type of the get method
> > paramete r is an any, this will automatically support both single and
> > array values.  For example,
> >
> > ---When retrieving the record of a single key index they do this:
> >     var request = index.get("Israel Hilerio");
> >     request.onsuccess = function (evt) { var record = this.result; }
> >
> > ---When retrieving the record of a compound key index they will query like
> this:
> >     var request = index.get(["PM","IE"]);
> >     request.onsuccess = function (evt) { var record = this.result; };
> >
> > . IDBIndex.getKey will be able to take in an array value.  Each value in the
> array will be mapped against the compound key defined in the
> IDBObjectStore and the record will be queried using all of the compound key
> values specified in the array.  The result will be an array of values that can be
> accessed using the property order of the compound key.
> 
> Why is the result an array of values? Isn't it just a primary key (which may or
> may not be a compound key?)
> 

I'm not suggesting we change the type of IDBRequest.result.  I expect it to continue to be of type any.  
If the key is a single key, it will continue to behave like today:

var request = index.getKey("Israel Hilerio");
request.onsuccess = function (evt) { var primaryKey = this.result; };

However, I do expect the result of a compound key to be different from a result of a single key.  Thus, we would probably have to define a new list type that holds the value of the compound keys:

IDBKeyList {
   readonly attribute unsigned long length;
   getter any item(unsigned long index);
};

This will allow us to retrieve the various key values as a list:
var request = index.getKey(["PM","IE"]);
request.onsuccess = function (evt) { 
  var firstKey = this.result[0]; 
  var secondKey = this.result[1];
};

In a similar fashion, I would expect that you could pass in any array like object (has a length property) to the IDBIndex.getKey method so we can treat it as an array.

> > Because the current type of the get method parameter is an any and the
> > type of the IDBRequest.result is an any, this will automatically
> > support both single and array values.  For example,
> >
> > ---When retrieving the primaryKey of a single key record they do this:
> >     var request = index.getKey("Israel Hilerio");
> >     request.onsuccess = function (evt) { var primaryKey = this.result;
> > }
> >
> > ---When retrieving the primaryKey of a compound key record they will
> query like this:
> >     var request = index.getKey(["PM","IE"]);
> >     request.onsuccess = function (evt) { var firstKey =
> > this.result[0]; var secondKey = this.result[1] };
> >
> > ---This will also support an indexed property that doesn't contain any
> arrays but the primary key of the record is an array.  Notice that passing a
> string into getKey will return an array as the result.
> >     var request = index.getKey("Israel Hilerio");
> >     request.onsuccess = function (evt) { var firstKey =
> > this.result[0]; var secondKey = this.result[1] };
> >
> > . IDBCursor.key and IDBCursor.primaryKey won't have to change
> > signature since they are already any attributes.  The current
> > definition should allow them to return an array if the key or
> > primaryKey is a compound key.  For example,
> >
> > ---When retrieving the value of a single key they do this:
> >     var myKey = cursor.key;
> >
> > ---When retrieving the value of a compound key they will do this:
> >     var myFirstKey = cursor.key[0];
> >     var mySecondKey = cursor.key[1];
> >
> > . The autoInc property will only apply to the first element on the compound
> key.  This will be consistent with our proposed KeyRange suggestion.
> >
> > . We should change the signature of IDBObjectStore.keyPath to be
> DOMStringList instead of DOMString.  This will make it more intuitive that it
> supports arrays.
> >
> > Let me know what you think.
> >
> > Israel
> >
> >
> >

Received on Tuesday, 30 August 2011 20:45:29 UTC