dumbmatter / fakeIndexedDB

A pure JS in-memory implementation of the IndexedDB API
Apache License 2.0
562 stars 69 forks source link

orderBy support #72

Closed ivelin closed 2 years ago

ivelin commented 2 years ago

When used with Dexie and jest, table.orderBy("someIndexedNonPrimaryKey") returns an empty result, while Dexie with indexeddb returns the expected list of records.

Related issue in Dexie's repo: https://github.com/dfahlander/Dexie.js/issues/1423

dumbmatter commented 2 years ago

If you can provide a self-contained reproduction of this issue, I would be happy to investigate!

ivelin commented 2 years ago

Hi Jeremy (@dumbmatter),

Thank you for looking at this issue. I tried to isolate it into a single jest test file that depends on Dexie and fakeIndexeddb only. Here is the gist.

While working on the gist I realized that this may be an indexeddb spec related issue. Not sure if you have the answer.

I expect orderBy on a non-unique, secondary key to return all records in the table in some reasonable order. For records that have an empty value for the ordering key, I expect them to show up at the beginning or the end of the ordered array, instead of not-appearing at all in the result.

Thank you again. This is an incredibly helpful project!

Ivelin

dumbmatter commented 2 years ago

Here is a minimal reproduction that runs in Node.js or in the browser:

(async () => {
  let Dexie;
  if (typeof require !== "undefined") {
    require("fake-indexeddb/auto");
    Dexie = require("dexie");
  } else {
    Dexie = (await import("https://unpkg.com/dexie?module")).Dexie;
  }

  const localdb = new Dexie("test")

  localdb.version(1).stores({
    test: "&primaryKey, indexKey"
  })

  const getAll = async () => {
    const array = await localdb.test.toArray();
    return array;
  };

  const getAllSorted = async () => {
    const array = await localdb.test.orderBy("indexKey").toArray();
    return array;
  };

  await localdb.test.clear();
  await localdb.test.put({
    primaryKey: 0,
  });

  const array = await getAll();
  console.log(array);

  const array2 = await getAllSorted();
  console.log(array2);
})();

I get the same output with both:

$ node test.js
[ { primaryKey: 0 } ]
[]

so I am going to close this issue, but feel free to reopen if I am missing something :)

I expect orderBy on a non-unique, secondary key to return all records in the table in some reasonable order. For records that have an empty value for the ordering key, I expect them to show up at the beginning or the end of the ordered array, instead of not-appearing at all in the result.

You could just sort them in JS after retrieving them from the DB, without using the index. Unless you have some very special situation (like if you're doing this same operation a billion times on large arrays), you would probably not notice any performance difference.

ivelin commented 2 years ago

OK, fair enough. Thank you for the prompt turnaround! Hope you enjoy the rest of your weekend :)