7

I was wondering if it is possible to perform a search on an indexeddb object store using wildcards. It would be handy to find all object with a key beginning with '555' for example

Daksh Shah
  • 2,997
  • 6
  • 37
  • 71
Jeanluca Scaljeri
  • 26,343
  • 56
  • 205
  • 333

5 Answers5

6

This is possible out of the box using either compound keys or key fragments. The way keys work in IndexedDB is that you generate a "keyRange" object and pass it to your cursor invocation. The keyrange passes info like "start at A and end at Z, inclusive."

By nature, there is partial matching built into this; the downside is that your cursor will return any keys that come between your keys and you might have to filter down those results further.

Say you have these words as keys in a object store:

  • Aardvark
  • Apple
  • Google
  • Microsoft

The key range "A to Z, inclusive" would return all of these but "Ap to Z, inclusive" would return just the last three.

Another technique I've used to implement this is by passing a "filter" function to my methods that invoke IndexedDB. Inside the methods onsuccess callback, pass the result (event.target.result) through your filter function and if it returns true then call your method invoker's onsuccess callback.

Matt Jacobsen
  • 5,814
  • 4
  • 35
  • 49
buley
  • 28,032
  • 17
  • 85
  • 106
5

Yes it is feasible to use wildcards, sort of.

I can't yet vote or even comment on previous answers (hmmm...) so I'll just repeat user2025527's answer as it totally worked for my needs.

Use the bounds method and specify the base value for the 1st argument and the same value plus an extra character for the 2nd argument.

In most cases the extra character character should be the last one in your charset: \uffff

But you're free to decide what constitutes the limit, especially when dealing with localization.

Lest say you have the following values in your index:

  • A
  • AB
  • B
  • BA
  • BB
  • C

To find everything stating with "BA" you should use

var range = IDBKeyRange.bound("BA", "BA" + '\uffff');
SVDB
  • 51
  • 1
  • 1
2

It isn't possible by default, but my library i wrote for the indexeddb supports it. Try linq2indexeddb.

Rémi
  • 3,867
  • 5
  • 28
  • 44
Kristof Degrave
  • 4,142
  • 22
  • 32
1

Search is also possible with wildcards in indexeddb see link IndexedDB Fuzzy Search

for wildcard below should work: var range = IDBKeyRange.bound("555", "555" + '\uffff');

Or else can use Linq2indexeddb library to make use of like.

Community
  • 1
  • 1
user2025527
  • 109
  • 2
  • 12
0

Here's a multiple key index example for reference. This is useful if you want to sort on the second key but only select on the first key. Also, FYI, you can define the primary key the same way with an array if so desired.

const customerData = [
    { id: 1, sort: "888", name: "Bill",   email: "bill@company.com" },
    { id: 2, sort: "111", name: "Donna",  email: "donna1@home.org" },
    { id: 3, sort: "222", name: "Donna",  email: "donna2@home.org" },
    { id: 4, sort: "999", name: "Andy",   email: "andy@home.org" },
    { id: 5, sort: "444", name: "George", email: "george@home.org" },
    { id: 6, sort: "222", name: "Tim",    email: "tim@home.org" },
    { id: 7, sort: "111", name: "Luke",   email: "luke@home.org" }
];

const objectStore = db.createObjectStore("customers", { keyPath: "id" });
objectStore.createIndex("multiple", ["name","sort"], { unique: false });

const index = objectStore.index("multiple");
const boundRange = IDBKeyRange.bound(["Donna",""], ["Donna",""+'\uffff']);
// for numeric columns use 0 instead of ""
//const boundRange = IDBKeyRange.bound(["Donna",0], ["Donna",0+'\uffff']);
index.openCursor(boundRange, "prev").onsuccess = (event) => {
        const cursor = event.target.result;
        if (cursor) {
            console.error(`${cursor.key}, name: ${cursor.value.name}, sort: ${cursor.value.sort}, email: ${cursor.value.email}`);
            cursor.continue();
        }
    };