bramski / angular-indexedDB

An angularjs serviceprovider to utilize indexedDB with angular
165 stars 49 forks source link

Is querying over multi entry indexes implemented? #69

Closed MrFurther closed 8 years ago

MrFurther commented 8 years ago

I'm trying to query against an index that's multi entry (array of strings as key), and getting empty results. Am I missing something or is it not implemented in the repository?

Here's the code I'm using:

$scope.searchStaff = function(staff){
  $indexedDB.openStore('records', function(store){
    $scope.lostone = staff.name;
    var find = store.query();
    find = find.$eq($scope.lostone);
    find = find.$index("pax_idx");
    store.eachWhere(find).then(function(e){
        $scope.foundstaff = e;
        console.log($scope.foundstaff);
    });
  });
};
schmod commented 8 years ago

I just did a quick check against my own code (which uses multiple indices), and this seems to be working correctly.

Looking at the source code, Query::$index() is very straightforward, and just sets an indexName parameter on the Query:

      $index: (indexName) ->
        @indexName = indexName
        this

eachWhere() is similarly straightforward, and calls store.index(indexName) if indexName is not falsy. (Note that store.index() is a native function provided by the browser, and is indeed the method that we'd want to be calling here)

eachWhere: (query) ->
    defer = @defer()
    indexName = query.indexName
    keyRange = query.keyRange
    direction = query.direction
    req = if indexName
      @store.index(indexName).openCursor(keyRange, direction)
    else
      @store.openCursor(keyRange, direction)
    @_mapCursor(defer, ((cursor) -> cursor.value), req)
    defer.promise

If you're not familiar with CoffeeScript, the compiled JS is very straightforward:

req = indexName ? this.store.index(indexName).openCursor(keyRange, direction) : this.store.openCursor(keyRange, direction);

I stepped through my own code in a debugger, and store.index() does indeed get called with the correct index name.

A slightly-modified version of my code is as follows:

$indexedDB.openStore('myStore', store => {
    var query = store.query().$index('expiration').$lt(oldest);
    return store.findWhere(query).then(items => {
        console.log(items);
    });
});

Mind sharing the portion of code where you create this index and/or add records? I think something else is going wrong here.

MrFurther commented 8 years ago

@schmod many thanks for taking a look!

Here's the part creating the index:

var objStore = db.createObjectStore('records', {keyPath: 'ssn', autoIncrement: true});
objStore.createIndex('date_idx', 'date', {unique: false});
objStore.createIndex('pax_idx', 'pax', {unique: false}, {multiEntry: true});

And here's how I add the records:

$scope.addRecord = function (records) {
  $indexedDB.openStore('records', function(store){
    $scope.newrecord = {
      "pax": $scope.paxlist,
    }
    store.insert($scope.newrecord).then(function(e){});
};

As you can see on the pic, the pax_idx contains the array as key with strings as values. Even so when I do the query I get empty array as result.

issue

schmod commented 8 years ago

The entire paxList array is getting stored as your key, which probably isn't what you want.

objStore.createIndex('pax_idx', 'pax', {unique: false}, {multiEntry: true});

needs to change to:

objStore.createIndex('pax_idx', 'pax', {unique: false, multiEntry: true});

at which point, "Anna", "John", and "Martha" should all be individual keys in pax_idx.

schmod commented 8 years ago

@MrFurther Did you ever resolve your issue? Can we close this?