2016-04-13 125 views
3

我目前使用Dexie.js在本地存儲數據。我有3個不同的表,它們通過使用外鍵相互連接。我設法設置架構並插入相應的數據。但是,當我想要檢索數據時,我找不到如何加入不同表的示例。Dexie.js - 如何連接表?

下面是一個例子:

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); 
    }); 
    }); 
}); 

回答

4

下面是如何連接的結果。免責聲明:代碼未經測試!

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()以加快查詢速度並獲得更可靠的原子結果。

+0

我希望這是一個有點* *更直觀;-) – cmroanirgo

1

不幸的是,我來到這裏,從谷歌尋找實際加入,你知道,那種東西:

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)}`) 
     }); 
})