如何在 indexeddb 中更新而不是覆盖所有数据?

How to update in indexeddb instead of override all the data?

我真的很喜欢 indexeddb 的这种非常简单的使用,但我试图弄清楚如何进行更新。

我已经看到 .put 应该为此工作,但是当我尝试这个时,它只会覆盖 ID 12345 的所有数据。我错过了什么?

这是我在下面使用的:

store.put({id: 12345, 姓名: {名字: "John", 姓氏: "Doe"}, 年龄: 42});

store.put({id: 12345, 姓名: {first: "somethingelse"}, 年龄: 42});

完整代码:

      var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.shimIndexedDB;

      // Open (or create) the database
      var open = indexedDB.open("MyDatabase", 1);

      // Create the schema
      open.onupgradeneeded = function() {
          var db = open.result;
          var store = db.createObjectStore("MyObjectStore", {keyPath: "id"});
          var index = store.createIndex("NameIndex", ["name.last", "name.first"]);
      };

      open.onsuccess = function() {
          // Start a new transaction
          var db = open.result;
          var tx = db.transaction("MyObjectStore", "readwrite");
          var store = tx.objectStore("MyObjectStore");
          var index = store.index("NameIndex");

          // Add some data
          store.put({id: 12345, name: {first: "John", last: "Doe"}, age: 42});
          store.put({id: 12345, name: {first: "somethingelse"}, age: 42});

          // Query the data
          var custInfo = store.get(12345);

          custInfo.onsuccess = function() {
              alert("ID " + custInfo.result.id + " age " +custInfo.result.age + " name " + custInfo.result.name.first+ custInfo.result.name.last);  // => "John"
              // alert(getJohn.result.name.first);  // => "John"
          };

          // Close the db when the transaction is done
          tx.oncomplete = function() {
              db.close();
          };
      }

如果我正确理解您的问题,那么我会指出调用 put 不等同于 SQL 更新。您不能使用单个请求仅替换对象存储中对象的某些属性。将新对象放入商店时,如果具有相同键路径 (id) 的另一个对象已经存在,则该现有对象将被完全替换。 indexedDB 不会修改存储中的现有对象,一次属性,而是用新对象完全替换旧对象。

如果您只想替换对象的某些属性,请使用两个请求。一个请求获取存储中的现有对象,第二个请求存储修改后的对象。在 get 和 put 之间,对对象进行更改。

类似这样的伪代码:

function updateSomeProps(db, id) {
  var tx = db.transaction(...);
  tx.oncomplete = _ => {
    console.log('finished updating object with id', id);
  };

  var store = tx.objectStore(...);
  var getRequest = store.get(id);
  getRequest.onsuccess = _ => {
     var obj = getRequest.result;
     if(!obj) {
       console.log('no matching object for id, canceling update', id);
       return;
     }

     console.log('loaded object to modify', obj);

     // make some changes to the properties of the object loaded 
     // in memory
     obj.age = 42;
     obj.firstname = 'asdf';
     delete obj.lastname;

     // now store the new object in place of the old object
     console.log('storing new object in place of old', obj);
     store.put(obj);
  };
}

function connectAndChangeStuff(id) {
  var openRequest = indexedDB.open(...);
  openRequest.onsuccess = _ => {
    var db = openRequest.result;
    updateSomeProps(db, 12345);
    db.close(); // optional
  };
}