我在尝试使用事务中的 put() 方法更新现有记录的“标题”字段时收到此错误。我有一个名为“hotkey”的字段,它有一个具有 unique: true 约束的索引。
以下是相关代码:
request3.onupgradeneeded = (event) => {
console.log('INSIDE onupgradeneeded for hotkeys', event);
handles["db3"] = event.target.result;
// Create an objectStore to hold information about our hotkeys.
const hotkeyStore = handles["db3"].createObjectStore(dbName3, {autoIncrement: true});
// Create an index to search hotkeys by letter. No duplicates
hotkeyStore.createIndex("hotkey", "hotkey", { unique: true });
hotkeyStore.createIndex("sort", "sort", { unique: false });
};
async function updateRecord(dbName, payload) {
return new Promise(async (resolve, reject) => {
setTable(dbName);
// open a read/write db transaction, ready for adding the data
const transaction = handles[activeDB].transaction([dbName], "readwrite");
// create an object store on the transaction
const objectStore = transaction.objectStore(dbName);
console.log(objectStore.keyPath);
const keyToUse = objectStore.keyPath !== null ? objectStore.keyPath : 'key';
console.log(payload);
for(let record of payload) {
console.log("WORKING ON: ", record);
if (!record.hasOwnProperty(keyToUse)) {
console.log('keypath for record not present in record, canceling update', record);
resolve(false);
}
var id = record[keyToUse];
if (keyToUse == 'key') id = parseInt(id);
console.log('Searching for record with keyPath ', id);
const getRequest = objectStore.get(id);
getRequest.onsuccess = function () {
var obj = getRequest.result;
if(!obj) {
console.log('no matching object for id, canceling update', id);
resolve(false);
return;
}
console.log('loaded object to modify', obj);
// make some changes to the properties of the object loaded
// in memory
Object.keys(record).forEach(key => {
if (key !== keyToUse && record[key] !== obj[key]) {
console.log('UPDATE TO ' + key);
const value = record[key];
obj[key] = value;
}
});
// now store the new object in place of the old object
console.log('storing new object in place of old', obj);
objectStore.put(obj);
};
}
transaction.done;
transaction.oncomplete = function () {
console.log("ALL PUT TRANSACTIONS COMPLETE.");
resolve(true);
}
transaction.onerror = function (event) {
console.log("PROBLEM UPDATING RECORDS.", event.target.error);
resolve(false);
}
});
}
这是控制台日志输出:
null
DBManager.js:164 [{…}]0: {title: 'Not Qualified', description: 'Description', hotkey: 'x', sort: '1', key: '2'}length: 1[[Prototype]]: Array(0)
DBManager.js:166 WORKING ON: {title: 'Not Qualified', description: 'Description', hotkey: 'x', sort: '1', key: '2'}
DBManager.js:173 Searching for record with keyPath 2
DBManager.js:183 loaded object to modify {title: 'N/A', description: 'Description', hotkey: 'x', sort: '1'}
DBManager.js:188 UPDATE TO title
DBManager.js:195 storing new object in place of old {title: 'Not Qualified', description: 'Description', hotkey: 'x', sort: '1'}
DBManager.js:207 PROBLEM UPDATING RECORDS. ConstraintError: Unable to add key to index 'hotkey': at least one key does not satisfy the uniqueness requirements.
configuration.js:252 false
DBManager.js:314 FAILED TO OPEN DB.
有人可以协助以正确的方式更新 IndexedDB 中具有唯一索引的记录吗?
由于您的热键是唯一的约束,请确保数据库中不存在您尝试为热键设置的值。您可以先使用 select First 进行检查,如果该热键值已经存在,则可以返回任何错误。
async function updateRecord(dbName, payload) {
return new Promise(async (resolve, reject) => {
setTable(dbName);
const transaction = handles[activeDB].transaction([dbName], "readwrite");
const objectStore = transaction.objectStore(dbName);
const keyToUse = objectStore.keyPath !== null ? objectStore.keyPath : 'key';
for (let record of payload) {
if (!record.hasOwnProperty(keyToUse)) {
console.log('keypath for record not present in record, canceling update', record);
resolve(false);
}
const id = keyToUse === 'key' ? parseInt(record[keyToUse]) : record[keyToUse];
const getRequest = objectStore.get(id);
getRequest.onsuccess = async function () {
const existingRecord = getRequest.result;
if (!existingRecord) {
console.log('no matching object for id, canceling update', id);
resolve(false);
return;
}
if (record.hotkey && record.hotkey !== existingRecord.hotkey) {
const hotkeyIndex = objectStore.index("hotkey");
const hotkeyRequest = hotkeyIndex.get(record.hotkey);
hotkeyRequest.onsuccess = function () {
const conflictingRecord = hotkeyRequest.result;
if (conflictingRecord && conflictingRecord[keyToUse] !== id) {
console.log("Conflict detected in 'hotkey' field. Aborting update.");
resolve(false);
return;
}
updateObjectStore(objectStore, existingRecord, record);
};
hotkeyRequest.onerror = function (event) {
console.log("Error checking for hotkey conflict:", event.target.error);
resolve(false);
};
} else {
updateObjectStore(objectStore, existingRecord, record);
}
};
}
transaction.oncomplete = function () {
console.log("ALL PUT TRANSACTIONS COMPLETE.");
resolve(true);
};
transaction.onerror = function (event) {
console.log("PROBLEM UPDATING RECORDS.", event.target.error);
resolve(false);
};
});
}
您始终可以创建辅助函数,但这是可选的
function updateObjectStore(objectStore, existingRecord, newRecord) {
Object.keys(newRecord).forEach(key => {
if (newRecord[key] !== existingRecord[key]) {
existingRecord[key] = newRecord[key];
}
});
objectStore.put(existingRecord);
}