From dbbbc81b36170923d1cff2e5d3b59e01a886a787 Mon Sep 17 00:00:00 2001 From: Joe Gaudet Date: Mon, 23 Mar 2020 14:36:51 -0700 Subject: [PATCH] Add support for multi index querying --- .gitignore | 1 + addon/services/indexed-db.js | 57 +++++++++++++++++++++--------------- package.json | 1 + 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index c40a1b2..55dbd6a 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ /npm-debug.log* /testem.log /yarn-error.log +.idea # ember-try /.node_modules.ember-try/ diff --git a/addon/services/indexed-db.js b/addon/services/indexed-db.js index d6d9d1a..872ba4b 100644 --- a/addon/services/indexed-db.js +++ b/addon/services/indexed-db.js @@ -3,7 +3,7 @@ import { set, get } from '@ember/object'; import { Promise } from 'rsvp'; import { later } from '@ember/runloop'; import { typeOf as getTypeOf } from '@ember/utils'; -import { A as array } from '@ember/array'; +import { A as array, isArray } from '@ember/array'; import { registerWaiter, unregisterWaiter, @@ -11,6 +11,7 @@ import { import { task, timeout } from 'ember-concurrency'; import { log } from 'ember-indexeddb/utils/log'; import Dexie from 'dexie'; +import { assert } from '@ember/debug'; /** * This service allows interacting with an IndexedDB database. @@ -477,7 +478,7 @@ export default class IndexedDbService extends Service { } @task(function* (config) { - let { databaseName, version, stores, data } = config; + let {databaseName, version, stores, data} = config; log('===================================='); log('Importing database dump!'); @@ -577,15 +578,15 @@ export default class IndexedDbService extends Service { } } - // Only one, then do a simple where - if (keys.length === 1) { - let key = keys[0]; - return db[type].where(key).equals(query[key]); - } - // Order of query params is important! - let { schema } = db[type]; - let { indexes } = schema; + let {schema} = db[type]; + let {indexes} = schema; + let indexMap = indexes.reduce((acc, index) => { + let keyPath = get(index, 'keyPath'); + acc[keyPath] = index; + + return acc; + }, {}); // try to find a fitting multi index // only if the client supports compound indices! @@ -609,10 +610,7 @@ export default class IndexedDbService extends Service { // If a multi index is found, use it if (multiIndex) { let keyPath = get(multiIndex, 'keyPath'); - let compareValues = array(); - keyPath.forEach((key) => { - compareValues.push(query[key]); - }); + let compareValues = keyPath.map((key) => query[key]); let keyName = get(multiIndex, 'name'); return db[type].where(keyName).equals(compareValues); @@ -620,15 +618,28 @@ export default class IndexedDbService extends Service { } // Else, filter manually - Object.keys(query).forEach((i) => { - if (!promise) { - promise = db[type].where(i).equals(query[i]); - } else { - promise = promise.and((item) => get(item, i) === query[i]); - } - }); - - return promise; + return Object.entries(query) + .reduce( + (query, [queryKey, queryValue], i) => { + let index = indexMap[queryKey]; + + assert(index, `You are attempting to query ${queryKey} which is not a valid index for ${type}`); + + let isMulti = index.multi && isArray(queryValue); + let first = i === 0; + + if (first) { + return isMulti + ? query.where(queryKey).anyOf(...queryValue) + : query.where(queryKey).equals(queryValue); + } else { + let predicate = isMulti + ? (item) => get(item, queryKey).any(_ => queryValue.includes(_)) + : (item) => get(item, queryKey) === queryValue; + + return query.and(predicate); + } + }, db[type]); } _mapItem(type, item) { diff --git a/package.json b/package.json index c445dd5..42244d0 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "release": "release-it" }, "dependencies": { + "@babel/plugin-proposal-class-properties": "^7.8.3", "dexie": "^2.0.4", "ember-auto-import": "^1.5.3", "ember-cli-babel": "^7.18.0",