2017-03-07 5 views
2

Blob 중복 레코드가 IndexedDB에있는 것을 방지하는 기본 제공 솔루션이 있습니까?IndexedDB에서 중복 된 Blob 객체 방지

음악 상점을위한이 스키마는 id, title, album, artwork이며이 앨범에는 같은 앨범의 2 곡을이 상점에 추가하고 싶습니다 (대부분 아트 워크 저작물이 같을 가능성이 큽니다). 내장 된 작품을 한 번만 자동 저장하는 방법이 있습니까?

나는 시도했다 :

  • 내가 artwork 인덱스에 unique 플래그를 설정하려고했으나 두 번째 노래의 삽입 전후 데이터베이스의 크기를 확인 후 (chrome://settings/cookies을 사용하여), 작품은 두 번 저장됩니다.

  • 그런 다음 동일한 플래그를 사용하여 별도의 저장소 (스키마로 idartwork 만 사용)에 아트 워크를 저장하려고했으나 작동하지 않았습니다.


var database = new Dexie('TheDatabase'); 
database.version(1).stores({artworks: '++id, &artwork'}); 

var dbArt = database.artworks; 

var artworkBlob = getBlob(image); 
dbArt.put(artworkBlob); 

//later: 
dbArt.put(artworkBlob); 

나는 어떤 방법으로 unique 플래그를 오용하고 있습니까? Blob 개체에서 지원되지 않습니까?

답변

3

IndexedDB는 Blob 저장을 지원하지만 Blob 인덱싱을 지원하지 않습니다. 인덱서 블 속성은 문자열, 숫자, 날짜 또는 배열 형식 일 수 있습니다. < 문자열 | 번호 | 날짜는 >입니다. 그렇지 않다면, IndexedDB는 자동으로 특정 객체를 색인하기 위해 무시할 것입니다.

또한 샘플 코드에서 artwork 테이블을 참조하지 않고 blob 속성이 포함 된 문서를 넣는 대신 blob을 단독으로 넣으려고합니다.

대신 할 수있는 것은 얼룩 콘텐츠의 해시/다이제스트를 계산하고 고유 색인을 사용하여 색인을 생성 할 수있는 문자열로 저장하는 것입니다.

var dbArt = new Dexie('TheDatabase'); 
dbArt.version(1).stores({ 
    artworks: ` 
     ++id, 
     title, 
     album, 
     &artworkDigest` // & = unique index of the digest 
}); 

var artworkBlob = getBlob(image); // get it somehow... 

// Now, compute hash before trying to put blob into DB 
computeHash(artworkBlob).then(artworkDigest => { 

    // Put the blob along with it's uniqely indexed digest 
    return dbArt.artworks.put({ 
     title: theTitle, 
     album: theAlbum, 
     artwork: artworkBlob, 
     artworkDigest: artworkDigest 
    }); 
}).then(()=>{ 
    console.log("Successfully stored the blob"); 
}).catch(error => { 
    // Second time you try to store the same blob, you'll 
    // end up here with a 'ConstraintError' since the digest 
    // will be same and conflict the uniqueness constraint. 
    console.error(`Failed to store the blob: ${error}`); 
}); 

function computeHash (blob) { 
    return new Promise((resolve, reject) => { 
     // Convert to ArrayBuffer 
     var fileReader = new FileReader(); 
     fileReader.onload =() => resolve(filerReader.result); 
     fileReader.onerror =() => reject(filerReader.error); 
     fileReader.readAsArrayBuffer(blob); 
    }).then (arrayBuffer => { 
     // Compute Digest 
     return crypto.subtle.digest("SHA-256", arrayBuffer); 
    }).then (digest => { 
     // Convert ArrayBuffer to string (to make it indexable) 
     return String.fromCharCode.apply(
      null, new Uint8Array(digest)); 
    }); 
}; 

나는 또한 나의 샘플이 표시되지 않습니다 우리는 어쨌든 ArrayBuffer에 방울을 읽을 수 있기 때문에 (오히려 BLOB보다 ArrayBuffer를 저장하는 것이 좋습니다,하지만 당신은 두 개의 서로 다른 기능으로 computeHash()을 분할 할 수 있습니다. - blob을 ArrayBuffer로 읽어 들이고, 다른 하나는 해쉬합니다 .Buffer 대신 ArrayBuffer를 저장하면 Safari 및 이전 버전의 firefox에서는 오류가 발생하지 않습니다.

사이드 노트 : IndexedDB 2.0에서 ArrayBuffers는 색인 가능합니다 (그러나 Blob은 아직 없습니다). 그러나 모든 데이터베이스에서 큰 값을 인덱싱하지 않는 것이 좋습니다. 다이제스트를 색인화하는 것이 더 좋습니다.

+0

해시 코드 사용을 권합니다. – Josh

+0

실제로 (* SparkMD5를 사용하여) 별도의 저장소에 아트웍을 저장하기위한 해싱 방법을 구현했지만 그럴 필요가 없다고 생각합니다. 'IndexedDB' 색인 및 고유 제한. Blob이 지원되지 않을 수도 있다고 생각하지 않았다. –

+0

예, 코드 전송 오류였습니다. 결정된. –