Как добавить в массив в IndexedDB отфильтрованный по идентификатору? - PullRequest
0 голосов
/ 05 октября 2018

Код инициализации:

let dbPormise = null;
const OBJECT_STORE_NAME = 'pages';
const DB_NAME = 'tracking-log';

Чтобы инициировать ObjectStore:

  dbPromise = idb.open(DB_NAME, 3, upgradeDB => {
    upgradeDB.createObjectStore(OBJECT_STORE_NAME, {
      autoIncrement: true,
      keypath: 'id'
    });
  });

Вот так я генерирую пустую запись в IndexedDB:

const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');

tx.objectStore(OBJECT_STORE_NAME).put(
    { id: newBucketID, data: [] });

Теперь, позже, у меня есть некоторые элементы, которые я хочу добавить в массив data для определенного id.

Вот как я пытался это сделать:

const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');

tx.objectStore(OBJECT_STORE_NAME).put(

{ id: localStorage.getItem("currentBucket"), data: item }

);

Схема

{
  data: Array
}

Каждый элемент имеет уникальный ключ, сгенерированный и предоставленный мной.

Однако это не работает ивозвращает ошибку: «Ключ уже существует в хранилище объектов».

Итак, как я могу добавить значение в поле внутри объекта IDB?

Ответы [ 2 ]

0 голосов
/ 09 октября 2018

Без уменьшенного примера сложно понять, что происходит.Лучший способ получить помощь - создать уменьшенный пример проблемы, например, наименьшее количество кода, необходимого для воссоздания проблемы, с которой вы столкнулись, а затем поместить его на что-то вроде jsbin.com или glitch.com, чтобы людиМне нужно щелкнуть ссылку, чтобы увидеть ошибку, которую вы видите.

Я не смог воссоздать ошибку, которую вы видите.У вас есть keypath, когда оно должно быть keyPath, но я не думаю, что это создает ошибку, которую вы видите.

В любом случае, вот как изменить запись в IDB:

async function main() {
  // Set up the database.
  const OBJECT_STORE_NAME = 'pages';
  const DB_NAME = 'tracking-log';

  const db = await idb.open(DB_NAME, 1, upgradeDB => {
    upgradeDB.createObjectStore(OBJECT_STORE_NAME, {
      autoIncrement: true,
      keyPath: 'id'
    });
  });

  // The OP didn't make it clear what this value was, so I'll guess.
  const newBucketID = 1;

  {
    // Create the record.
    const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
    tx.objectStore(OBJECT_STORE_NAME).put({ id: newBucketID, data: ['first value'] });
  }

  {
    const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
    // Get the record.
    const record = await tx.objectStore(OBJECT_STORE_NAME).get(newBucketID);
    // Modify it.
    record.data.push('second value');
    // Put the modified record back.
    tx.objectStore(OBJECT_STORE_NAME).put(record);
  }

  {
    // Read the value to confirm everything worked.
    const tx = db.transaction(OBJECT_STORE_NAME);
    const value = await tx.objectStore(OBJECT_STORE_NAME).get(newBucketID);
    console.log(value);
  }
}

main();

И вот этот пример: https://jsbin.com/dineguq/edit?js,console

0 голосов
/ 06 октября 2018

Не уверен насчет ошибки, но независимо от этого, основной способ добавления элемента будет выглядеть примерно так:

function addItem(db, bucketId, item) {
  return new Promise(addItemExecutor.bind(null, db, bucketId, item));
}

function addItemExecutor(db, bucketId, item, resolve, reject) {
  // Start a single writable transaction that we will use for two requests. One to 
  // find the corresponding bucket, and one to update it.
  const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');

  // If all requests completed without error, we are done
  tx.oncomplete = resolve;

  // If any request fails, the operation fails
  tx.onerror = event => reject(event.target.error);

  const store = tx.objectStore(OBJECT_STORE_NAME);

  // Go find the corresponding bucket object to update
  const findRequest = store.get(bucketId);
  findRequest.onsuccess = findRequestOnsuccess.bind(findRequest, bucketId, item, reject);
}

// React to the resolution of the get request
function findRequestOnsuccess(bucketId, item, reject, event) {
  const bucket = event.target.result;

  // If no bucket exists for that id then fail
  if(!bucket) {
    const error = new Error('No bucket found for id ' + bucketId);
    reject(error);
    return;
  }

  // Lazily init the data array property
  if(!bucket.data) {
    bucket.data = [];
  }

  // Add our item to the data array
  bucket.data.push(item);

  // Save the bucket object back into the bucket object store, completely replacing 
  // the bucket that was there before.
  const bucketStore = event.target.source;
  bucketStore.put(bucket);
}


async function someCallingCodeExampleAvoidingTopLevelAwait() {
  const bucketId = localStorage.currentBucket;
  const item = {foo:bar};

  const db = evilUnreliableGlobalDbVariableFromSomewhereMagicalForeverOpenAssumeInitialized;

  try {
    await addItem(db, bucketId, item);
  } catch(error) {
    console.debug(error);
  }

  // Leave the database connection open for page lifetime
}
...