Menu Close

IndexedDB Manipulation with Dexie — Orders and Joins

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.

Ordering

We can order queries with the between method.

For example, 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: "jane",
      lastName: 'smith',
      age: 39
    })
    await db.friends.put({
      firstName: "jane",
      lastName: 'wong',
      age: 28
    })
    const someFriends = await db.friends
      .where('[firstName+lastName]')
      .between(["jane", ""], ["jane", "uffff"])
      .toArray()
    console.log(someFriends)
  } catch (error) {
    console.log(error);
  }
})()

We call between with '' and 'uffff' in the 2nd entry to order the results by lastName .

Also, we can search for items with other methods that act as operators.

For instance, we can write:

(async () => {
  const db = new Dexie("friend_database");
  try {
    await db.version(1).stores({
      friends: '++id,firstName,lastName,age,shoeSize,interests'
    });
    await db.friends.put({
      firstName: "jane",
      lastName: 'smith',
      age: 39,
      shoeSize: 7,
      interests: ['sports', 'pets'],
      tags: []
    })
    await db.friends.put({
      firstName: "jane",
      lastName: 'wong',
      age: 28,
      shoeSize: 9,
      interests: [],
      tags: []
    })
    const someFriends = await db.friends
      .where('age').above(25)
      .or('shoeSize').below(8)
      .or('interests').anyOf('sports', 'pets', 'cars')
      .modify(friend => friend.tags.push("marketing-target"));
  } catch (error) {
    console.log(error);
  }
})()

We add the items with the age, shoeSize , and interests fields as index fields.

Then we search for the age with the where and above methods.

Then we use the or method to search for the shoeSize below a given size with the below method.

And we use the anyOf method to search if the given values are in the interests array.

Then we call modify to add the tags value to the array.

Retrieve First n Items

We can search for the first n items with the limit method.

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: "jane",
      lastName: 'smith',
      age: 39,
    })
    await db.friends.put({
      firstName: "jane",
      lastName: 'wong',
      age: 28,
    })
    const someFriends = await db.friends
      .orderBy("age")
      .reverse()
      .limit(5)
      .toArray();
    console.log(someFriends)
  } catch (error) {
    console.log(error);
  }
})()

We call orderBy to get the entries ordered by age .

We call reverse to sort them by reverse order.

limit limits the number of items returned to the given number.

Joining

We can join multiple tables together.

For example, we can write:

(async () => {
  const db = new Dexie('music');

  try {
    db.version(1).stores({
      albums: '++id,name,*tracks',
      bands: '++id,name,*albumIds'
    });

    const a1 = await db.albums.put({
      name: 'Arrival',
      year: 1974
    })

    const a2 = await db.albums.put({
      name: 'Waterloo',
      year: 1974
    })

    await db.bands.put({
      name: "Abba",
      albumIds: [a1, a2]
    })

    const bands = await db.bands
      .where('name')
      .startsWith('A')
      .toArray();

    const someBands = await Promise.all(bands.map(async band => {
      band.albums = await db.albums.where('id').anyOf(band.albumIds).toArray()
      return band
    }));
    console.log(someBands)
  } catch (error) {
    console.log(error);
  }
})()

We created the albums and bands tables.

Then we populate them with our own data.

a1 and a2 are the IDs for the album entries.

We use then to populate the albumId fields of the band .

Then we query the band with:

const bands = await db.bands
  .where('name')
  .startsWith('A')
  .toArray();

Then we add the albums to the band with:

const someBands = await Promise.all(bands.map(async band => {
  band.albums = await db.albums.where('id').anyOf(band.albumIds).toArray()
  return band
}));

We just attach the child items to a property of the parent.

Conclusion

We can order items and join multiple tables with Dexie.

Posted in JavaScript APIs