Dexie.js - 如何加入表格?

时间:2016-04-13 09:28:43

标签: javascript dexie

我目前正在使用Dexie.js在本地存储数据。我有3个不同的表,通过使用外键相互连接。我设法设置架构并插入相应的数据。但是,当我想要检索数据时,我找不到如何连接不同表的示例。

以下是一个例子:

var db = new Dexie('my-testing-db');
db.delete().then(function() {

  db.version(1).stores({
    genres: '++id,name',
    albums: '++id,name,year,*tracks',
    bands: '++id,name,*albumsId,genreId'
  });

  db.transaction('rw', db.genres, db.albums, db.bands, function() {
    var rock = db.genres.add({
        name: 'rock'
      }),
      jazz = db.genres.add({
        name: 'jazz'
      });

    var justLookAround = db.albums.add({
      name: 'Just Look Around',
      year: 1992,
      tracks: [
        'We want the truth', 'Locomotive', 'Shut me out'
      ]
    });

    var sickOfItAll = db.bands.add({
      name: 'Sick Of it All'
    });

    justLookAround.then(function(album_id) {
      rock.then(function(rock_id) {
        sickOfItAll.then(function(band_id) {
          db.bands.update(band_id, {
            genreId: rock_id,
            albumsId: [album_id]
          }).then(function(updated) {

          });
        });
      });
    });

  }).then(function() {
    //how to join the tables here????
    db.bands.each(function(band) {
      console.log(band);
    });
  });
});

2 个答案:

答案 0 :(得分:4)

以下是加入结果的方法。 Disclaimber:代码未经测试!

var all = Dexie.Promise.all;

function joinBands (bandCollection) {

    // Start by getting all bands as an array of band objects
    return bandCollection.toArray(function(bands) {

        // Query related properties:
        var genresPromises = bands.map(function (band) {
            return db.genres.get(band.genreId || 0);
        });
        var albumsPromises = bands.map(function (band) {
            return db.albums.where('id').anyOf(band.albumsId || []).toArray();
        });

        // Await genres and albums queries:
        return all ([
            all(genresPromises),
            all(albumsPromises)¨
        ]).then(function (genresAndAlbums) {

            // Now we have all foreign keys resolved and
            // we can put the results onto the bands array
            // before returning it:
            bands.forEach(function (band, i) {
                band.genre = genresAndAlbums[0][i];
                band.albums = genresAndAlbums[1][i];
            });
            return bands;
        });
    });
}

// Join all:
joinBands(db.bands.toCollection()).then(function (bands) {
    alert ("All bands: " + JSON.stringify(bands, null, 4));
}).catch(function (error) {
    alert ("Oops: " + error);
});

// Query and join:
joinBands(db.bands.where('genreId').anyOf([1,5,19]).limit(25)).then(function (bands) {
    alert ("Some bands: " + JSON.stringify(bands, null, 4));
}).catch (function (error) {
    alert ("Oops: " + error);
});

最好从事务中调用joinBands()以加快查询速度,并获得更可靠和原子化的结果。

答案 1 :(得分:2)

不幸的是,我从谷歌到这里寻找实际的加入,你知道,有类似的东西:

db.bands.where(...).equals(..).join(
  db.genres.where(...).etc(), 'genreId -> genres.id').then(
    function(band, genre) { ... });

我认为这更接近于原始提问者的要求,但根据@ david-fahlander提供的答案,似乎这个插件https://github.com/ignasbernotas/dexie-relationships可能会更容易一些,如果你'重新建立一个漂亮的对象树。

该插件的自述文件与您的示例非常相似,所以我在这里逐字复制:

<强>模式

请注意使用设置外键的->

import Dexie from 'dexie'
import relationships from 'dexie-relationships'

var db = new Dexie('MusicBands', {addons: [relationships]})

db.version(1).stores({
    genres: 'id, name',
    bands: 'id, name, genreId -> genres.id',
    albums: 'id, name, bandId -> bands.id, year'
});

<强>用法

db.bands
  .where('name').startsWithAnyOf('A', 'B') // can be replaced with your custom query
  .with({albums: 'albums', genre: 'genreId'}) // makes referred items included
  .then(bands => {
      // Let's print the result:
      bands.forEach (band => {
          console.log (`Band Name: ${band.name}`)
          console.log (`Genre: ${band.genre.name}`)
          console.log (`Albums: ${JSON.stringify(band.albums, null, 4)}`)
      });
})