Searching for compound indexes in IndexedDB

為{幸葍}努か 提交于 2019-11-29 14:46:59
  1. When you create an index on an array, the entries of your store only appear in the index if each element in the array that corresponds to a property in the underlying object has a defined value.

    To get around this obstacle, always store defined values in your underlying object store. For example, to represent a boolean property, use an integer, where 0 is false, and 1 is true. This way, each object in the store can appear in the index. indexedDB's behavior here is quite different than truthy/falsy handling in plain old javascript (where 0 == undefined ).

  2. The key range you specify when opening a cursor on a array-based index must use defined parameters for each element of the array.

    To get around this obstacle, you must specify all boundaries, even if those boundaries are not real values (e.g. like in my example you linked to, 200 as max age works because we can safely assume no one is 200 yrs old).

So to address your question, it might be a problem in your code in that one of the parameters to your boundaries variables (either [valueOneLower, valueTwoLower, valueThreeLower] or [valueOneUpper, valueTwoUpper, valueThreeUpper]) is not defined.

Based on your comments, I suggest that you test your expectations with indexedDB.cmp. It is pretty simple to write these tests. It does not require any database connection. Here is a pretty basic example to get you started:

// Build our test values

var lower1 = 1, lower2 = 1, lower3 = 1;
var upper1 = 3, upper3 = 3, upper3 = 3;
var middle1 = 2, middle2 = 2, middle3 = 2;

var lowerBound = [lower1,lower2,lower3];
var upperBound = [upper1,upper2,upper3];
var middleValue = [middle1,middle2,middle3];

// As the linked page provides, cmp returns -1 if first is less than second, 0 if equal, 1 if first is greater than second.

var lowerVsMiddle = indexedDB.cmp(lowerBound, middleValue);
console.log('Is %s < %s ? %s', lowerBound, middleValue, lowerVsMiddle == -1);
console.log('Is %s > %s ? %s', lowerBound, middleValue, lowerVsMiddle == 1);

var upperVsMiddle = indexedDB.cmp(upperBound, middleValue);
console.log('Is %s < %s ? %s', upperBound, middleValue, upperVsMiddle == -1);
console.log('Is %s > %s ? %s', upperBound, middleValue, upperVsMiddle == 1);

You should be able to answer your questions accurately by running tests like this.

I retrieved the relevant part of the indexedDB spec for you. First note that "An Array is only a valid key if every item in the array is defined and is a valid key...". This ties into whether the object will appear in the index, and also ties into whether your key parameters to either cmp or IDBKeyRange.bound/lowerBound/upperBound will work. Second, farther down, note the following:

Values of type Array are compared to other values of type Array as follows:

  1. Let A be the first Array value and B be the second Array value.
  2. Let length be the lesser of A's length and B's length.
  3. Let i be 0.
  4. If the ith value of A is less than the ith value of B, then A is less than B. Skip the remaining steps.
  5. If the ith value of A is greater than the ith value of B, then A is greater than B. Skip the remaining steps.
  6. Increase i by 1.
  7. If i is not equal to length, go back to step 4. Otherwise continue to next step.
  8. If A's length is less than B's length, then A is less than B. If A's length is greater than B's length, then A is greater than B. Otherwise A and B are equal.

From the KeyRange section: A key is in a key range if both the following conditions are fulfilled:

  • The key range lower value is undefined or less than key. It may also be equal to key if lowerOpen is false.
  • The key range upper value is undefined or greater than key. It may also be equal to key if upperOpen is false.

One more clarification now that I understand your question based on the comments and your further edits: Essentially indexedDB is providing a union behavior of the criteria but you want is an intersection. One way of solving this is to not think about the data in normal form at all, but to think about how to setup the data so it can be queried in the manner you want. It is interesting food for thought and I do not have an immediate answer for you.

Kyaw Tun

You need another compound index for that case.

Alternatively you can use key joining as describe here YDN-DB - Incorrect results using mixed data types with SortedMerge

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!