質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.84%

  • JavaScript

    14825questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

indexedDBで2つのキーを同時に抽出したい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 249

tajix_japan

score 65

下記のようなindexedDBを組みました。

dbName = 'mydb';
storeName  = 'mystore';
keyValue = 'MYID';YAMADA
keyValue = 'PASS';1234

下記のようにすることで、
<a href='./../index.html?uid=YAMADA'>インデックス</a>

というリンクを張ることができました。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8"/>
  <title>Indexed DataBase APIサンプル</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
</head>
<body>

<script>
var dbName = 'mydb';
var openReq  = indexedDB.open(dbName);
// DB名を指定して接続。DBがなければ新規作成される。
  openReq.onupgradeneeded = function(event){
  //onupgradeneededは、DBのバージョン更新(DBの新規作成も含む)時のみ実行
    console.log('db upgrade');
  }
  openReq.onsuccess = function(event){
  //onupgradeneededの後に実行。更新がない場合はこれだけ実行
    console.log('db open success');
    var db = event.target.result;
    // 接続を解除する
    db.close();
  }
  openReq.onerror = function(event){
  // 接続に失敗
    console.log('db open error');
  }
var storeName  = 'mystore';
var keyValue = 'MYID';
var openReq = indexedDB.open(dbName);
  openReq.onsuccess = function(event){
    var db = event.target.result;
    var trans = db.transaction(storeName, 'readonly');
    var store = trans.objectStore(storeName);
    var getReq = store.get(keyValue);
    getReq.onsuccess = function(event){
      if (event.target.result === undefined) {
        result.innerHTML = "指定したキーは存在しません。";
      } else {
        result.innerHTML ="<a href='./../index.html?uid=" + event.target.result.myvalue + ""'>インデックス</a>";
      }

    }
  }
</script>



<BR>上部表示
<BR>
<div id="result"/>
<BR>
下部表示
<BR>

</body>
</html>

今回やりたいこと

<a href='./../index.html?uid=YAMADA&pass=1234'>インデックス</a>

とユーザーIDだけでなくパスワードまでリンクにしたいと考えています。
(実際にはパスワードはSHA256化してます)

var storeName  = 'mystore';
var keyValue = 'MYID';
var openReq = indexedDB.open(dbName);
  openReq.onsuccess = function(event){
    var db = event.target.result;
    var trans = db.transaction(storeName, 'readonly');
    var store = trans.objectStore(storeName);
    var getReq = store.get(keyValue);
    getReq.onsuccess = function(event){
      if (event.target.result === undefined) {
        result.innerHTML = "指定したキーは存在しません。";
      } else {
        result.innerHTML ="<a href='./../index.html?uid=" + event.target.result.myvalue + ""'>インデックス</a>";

の部分を「IDとPASSの2階建て」にすれば簡単に行けそうでしたので、下記のように書き換えました。

var storeName  = 'mystore';

var keyValue = 'MYID';
var keyValue2 = 'PASS';

var openReq = indexedDB.open(dbName);
  openReq.onsuccess = function(event){

    var db = event.target.result;
    var trans = db.transaction(storeName, 'readonly');
    var store = trans.objectStore(storeName);
    var getReq = store.get(keyValue);

    var db2 = event.target.result2;
    var trans2 = db2.transaction(storeName, 'readonly');
    var store2 = trans2.objectStore(storeName);
    var getReq2 = store2.get(keyValue2);

    getReq.onsuccess = function(event){
      if (event.target.result === undefined) {
        result.innerHTML = "指定したキーは存在しません。";
      } else {
        result.innerHTML ="<a href='./../index.html?uid=" + event.target.result.myvalue + "&pws=" + event.target.result2.myvalue + "'>インデックス</a>";

var keyValue2 = 'PASS';に対応する部分として

新たに

var db2 = event.target.result2;
var trans2 = db2.transaction(storeName, 'readonly');
var store2 = trans2.objectStore(storeName);
var getReq2 = store2.get(keyValue2);

を付け加え、リンクを
<a href='./../index.html?uid=" + event.target.result.myvalue + "&pws=" + event.target.result2.myvalue + "'>インデックス</a>"
としたものです。

結果

Uncaught TypeError: Cannot read property 'transaction' of undefined

というエラーが出ました。

次にresult2ではなくtarget2も試してみましたが、

event.target.result2; → 
var db2 = event.target2.result; に変更し
<a href='./../index.html?uid=" + event.target.result.myvalue + "&pws=" + event.target2.result.myvalue + "'>とする。

Uncaught TypeError: Cannot read property 'result' of undefined

というエラーが出ました。

どうすれば
<a href='./../index.html?uid=YAMADA&pass=1234'>インデックス</a>
のようにIDとパスワードを引っ張ってくることができるのでしょうか?

よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

どのようにストアを作成しているのかがかかわってくると思うのですが、
例えば、以下のようにすればIDをキーにして、パスワードを取得できると思います。

let db = null;

class IDB {
    constructor(options) {
        this._dbName = options.databaseName || 'mydb';
        this._dbVersion = options.databaseVersion || 1;
        this._storeName = options.storeName || 'mystore';
        this._keyPath = options.keyPath;
        this._db = null;
        this._store = null;
    }

    open() {
        if(this._db) return;
        return new Promise((resolve, reject) => {
            if (this._db) {
                resolve();
            } else {
                const req = indexedDB.open(this._dbName, this._dbVersion);
                req.onsuccess = evt => {
                    this._db = req.result;
                    resolve();
                };
                req.onupgradeneeded = evt => {
                    this._db = req.result;
                    this._store = req.result.createObjectStore(this._storeName, { keyPath: this._keyPath, autoIncrement: this._autoIncrement });
                    req.transaction.oncomplete = evt => {
                        resolve();
                    }
                };
                req.onerror = evt => {
                    reject(req.error);
                };
            }
        });
    }

    async putOne(data, storeName) {
        return new Promise(async (resolve, reject) => {
            storeName = storeName || this._storeName; 
            if (!data) throw new Error('put no data');
            await this.open(); 
            const tx = this._db.transaction(this._storeName, 'readwrite');
            const store = tx.objectStore(this._storeName); 
            let err = null;
            tx.oncomplete = evt => { 
                if (err) { 
                    reject(err); 
                } else { 
                    resolve(data);
                }
            };
            tx.onerror = evt => {
                reject(tx.error);
            };
            const req = store.put(data);
            req.onerror = evt => {
                err = req.error; 
                err.data = data;
            }
            req.success = evt => {
                data[this._keyPath] = req.result;
            }
        });
    }

    async getOne(key) {
        return new Promise(async (resolve, reject) => {
            await this.open(); 
            const tx = this._db.transaction(this._storeName);
            const store = tx.objectStore(this._storeName);
            let res = null; 
            let err = null;
            tx.oncomplete = evt => { 
                if (err) {
                    reject(err);
                } else {
                    resolve(res);
                }
            };
            tx.onerror = evt => {
                reject(tx.error);
            };
            const req = store.get(key);
            req.onsuccess = evt => { 
                res = req.result;
            };
            req.onerror = evt => {
                err = req.error;
            };
        });
    }
}


const idb = new IDB({
    databaseName: 'mydb',
    storeName: 'mystore',
    keyPath: 'MYID',
});

async function idbPut(data) {
    try {
        await idb.open();
        idb.putOne(data);
    } catch(err) {
        console.log(err);
    }
} 

async function idbGet(id) {
    try {
        const res = await idb.getOne(id);
        return res.pass;
    } catch(err) {
        console.log(err);
    }  
}
// indexedDBにユーザー登録 
idbPut({MYID:'MYID', pass:'PASS'});  

// indexedDBからユーザー(のパス)を取得
idbGet('MYID').then(pass => console.log(pass));

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/01 21:56

    ありがとうございます。
    早速
    mydb, mystore, MYID, PASSW2 など自分の環境に合わせて試してみました。
    <script>
    let db = null;
    class IDB {
    constructor(options) {
    this._dbName = options.databaseName || 'mydb';
    this._dbVersion = options.databaseVersion || 1;
    this._storeName = options.storeName || 'mystore';
    this._keyPath = options.keyPath;
    this._db = null;
    this._store = null;
    }

    open() {
    if(this._db) return;
    return new Promise((resolve, reject) => {
    if (this._db) {
    resolve();
    } else {
    const req = indexedDB.open(this._dbName, this._dbVersion);
    req.onsuccess = evt => {
    this._db = req.result;
    resolve();
    };
    req.onupgradeneeded = evt => {
    this._db = req.result;
    this._store = req.result.createObjectStore(this._storeName, { keyPath: this._keyPath, autoIncrement: this._autoIncrement });
    req.transaction.oncomplete = evt => {
    resolve();
    }
    };
    req.onerror = evt => {
    reject(req.error);
    };
    }
    });
    }

    async putOne(data, storeName) {
    return new Promise((resolve, reject) => {
    storeName = storeName || this._storeName;
    if (!data) throw new Error('put no data');
    await this.open();
    const tx = this._db.transaction(storeName, 'readwrite');
    const store = tx.objectStore(storeName);
    let err = null;
    const tx = store.transaction;
    tx.oncomplete = evt => {
    if (err) {
    reject(err);
    } else {
    resolve(data);
    }
    };
    tx.onerror = evt => {
    reject(tx.error);
    };
    const req = store.put(data);
    req.onerror = evt => {
    err = req.error;
    err.data = data;
    }
    req.success = evt => {
    data[this._keyPath] = req.result;
    }
    });
    }

    async getOne(key) {
    return new Promise((resolve, reject) => {
    await this.open();
    const tx = req.transaction;
    let res = null;
    let err = null;
    tx.oncomplete = evt => {
    if (err) {
    reject(err);
    } else {
    resolve(res);
    }
    };
    tx.onerror = evt => {
    reject(tx.error);
    };
    req.onsuccess = evt => {
    res = req.result;
    };
    req.onerror = evt => {
    err = req.error;
    };
    });
    }
    }


    const idb = new IDB({
    databaseName: 'mydb',
    storeName: 'mystore',
    keyPath: 'MYID',
    });

    async function idbPut(data) {
    try {
    await idb.open();
    idb.putOne(data);
    } catch(err) {
    console.log(err);
    }
    }

    async function idbGet(id) {
    try {
    const pass = idb.getOne(id);
    return pass;
    } catch(err) {
    console.log(err);
    }
    }

    // indexedDBにユーザー登録
    idbPut({id:'MYID', pass:'PASS'});


    // indexedDBからユーザー(のパス)を取得
    const pass = await idbGet(id);

    </script>

    としてみたのですが、

    Uncaught SyntaxError: await is only valid in async function

    というエラーが出てブラウザ上では何も表示されませんでした。
    awaitは非同期関数でのみ有効とのことで、うまく表示されません。

    キャンセル

  • 2018/01/01 22:37

    解凍のコードを修正したので、コピペしなおしてください

    キャンセル

  • 2018/01/02 06:25

    お手数をお掛けし申し訳ございません。
    下記のエラーが出てしまい、やはり取得できませんでした。
    申し訳ございません。
    Uncaught (in promise) DOMException: Failed to execute 'put' on 'IDBObjectStore': Evaluating the object store's key path did not yield a value.
    at Promise (URL)
    at <anonymous>

    キャンセル

  • 2018/01/02 07:50

    開発ツールで、Applicationタブを開き、キーパスが何になっているか確認してください。

    キャンセル

  • 2018/01/02 08:33

    ありがとうございます。

    mystore → myvalueIndex と辿ると

    Key(key path: "myvalue")

    Primary key (key path: "mykey")

    となっております。

    キャンセル

  • 2018/01/02 10:22

    となると、
    store.put({myvalue:'MYID', pass:'PASS'})といった値を登録しなければなりません。
    createObjectStore()時にkyePathを設定しますが、例えば
    db.createObjectStore('hoge', {keyPath:'fuga'});
    として、ストアを作成した場合、
    store.put({fuga:'piyo', value: 'val'});
    というように、DBに登録するオブジェクトのキーにkeyPathで指定した'fuga'を含めなければなりません。
    このfugaキーがhogeストアのキーとなり、hogeストアから値を取得するとき、store.get('piyo')とすれば{fuga:'piyo', value: 'val'}が取得できます。

    キャンセル

  • 2018/01/02 12:25

    すみません。言葉足らずでした。
    下記のとおり登録されているようです。

    Application
    Start from key

    Key(key path: "mykey")
    "ID"
    Value
    ▼Object
    mykey; "ID"
    myvalue; "YAMADA"

    "PASS"
    Value
    ▼Object
    mykey; "PASS"
    myvalue; "123"

    となっております。

    キャンセル

  • 2018/01/02 12:50

    なぜ、わざわざ"ID"と"PASS"の2つに分けて登録しているのかがわからないのですが。
    2つに分けて登録すると、別途、2つの値を紐づけるプロパティが必要になってきますよね?
    2つに分けずに、
    store.put({mykey:"YAMADA", myvalue:"123"})
    と登録すれば
    store.get("YAMADA")で、{mykey:"YAMADA", myvalue:"123"}が取得できるのですが。

    キャンセル

  • 2018/01/02 14:01

    ありがとうございます。
    そもそもの設計が間違っているということですね。
    indexedDBは初めてなので、拾ってきたソースを改造しながらやったため
    根本が間違っているようです。
    頂きましたソースをベースに再度勉強しなおしてみます。
    ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.84%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • JavaScript

    14825questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。