Menu Close

IndexedDB Manipulation with Dexie — Complex Queries

IndexedDB is a way to store data in the browser.

It lets us store larger amounts of data than local storage in an asynchronous way.

Dexie makes working with IndexedDB easier.

In this article, we’ll take a look at how to start working with IndexedDB with Dexie.

Query and Modify Data

We can query for and modify data at the same time.

For example, we can write:

(async () => {
  const db = new Dexie("friend_database");
  try {
    await db.version(1).stores({
      friends: 'name,age'
    });
    await db.friends.put({
      name: "mary",
      age: 68
    })
    await db.friends.put({
      name: "jane",
      age: 28
    })
    await db.friends
      .where('age')
      .inAnyRange([
        [0, 18],
        [65, Infinity]
      ])
      .modify({
        discount: 0.5
      });
  } catch (error) {
    console.log(error);
  }
})()

We get all the entries of the friends table with age between 0 to 18 or 65 and up.

Then we call modify to change the discount field to 0.5.

Search for Entries with Any Condition

We can search for entries with our own condition with the filter method.

For example, we can write:

(async () => {
  const db = new Dexie("friend_database");
  try {
    await db.version(1).stores({
      friends: 'name,age'
    });
    await db.friends.put({
      name: "mary",
      age: 68
    })
    await db.friends.put({
      name: "jane",
      age: 28
    })
    const someFriends = await db.friends
      .filter(friend => /j/i.test(friend.name))
      .toArray();
    console.log(someFriends)
  } catch (error) {
    console.log(error);
  }
})()

We call filter with a callback that checks the friend.name value to see if it has the letter j in it.

Also, we can search for data with compound indexes.

For instance, we can write:

(async () => {
  const db = new Dexie("friend_database");
  try {
    await db.version(1).stores({
      friends: '++id,[firstName+lastName],age'
    });
    await db.friends.put({
      firstName: "mary",
      lastName: 'smith',
      age: 39
    })
    await db.friends.put({
      firstName: "jane",
      lastName: 'wong',
      age: 28
    })
    const someFriends = await db.friends
      .where('[firstName+lastName]')
      .equals(["jane", "wong"])
      .first();
    console.log(someFriends)
  } catch (error) {
    console.log(error);
  }
})()

We have the compound index [firstName+lastName] .

Then we can search for both fields together with the where method with the compound fields.

And equals with the value of each.

first returns the first result.

We search for the value of firstName and lastName together with equals .

We can make this query simpler with the where method:

(async () => {
  const db = new Dexie("friend_database");
  try {
    await db.version(1).stores({
      friends: '++id,[firstName+lastName],age'
    });
    await db.friends.put({
      firstName: "mary",
      lastName: 'smith',
      age: 39
    })
    await db.friends.put({
      firstName: "jane",
      lastName: 'wong',
      age: 28
    })
    const someFriends = await db.friends
      .where({
        firstName: "jane",
        lastName: "wong"
      })
      .first();
    console.log(someFriends)
  } catch (error) {
    console.log(error);
  }
})()

We can also use the get method to call where and first together:

(async () => {
  const db = new Dexie("friend_database");
  try {
    await db.version(1).stores({
      friends: '++id,[firstName+lastName],age'
    });
    await db.friends.put({
      firstName: "mary",
      lastName: 'smith',
      age: 39
    })
    await db.friends.put({
      firstName: "jane",
      lastName: 'wong',
      age: 28
    })
    const someFriends = await db.friends
      .get({
        firstName: "jane",
        lastName: "wong"
      })
    console.log(someFriends)
  } catch (error) {
    console.log(error);
  }
})()

Conclusion

We can make queries that modify data, queries that have more complex conditions, and queries with compound indexes with Dexie.

Posted in JavaScript APIs