Google 数据存储无法更新实体
Google Datastore can't update an entity
我在从 Google 数据存储中检索实体时遇到问题。这是我的代码:
async function pushTaskIdToCurrentSession(taskId){
console.log(`Attempting to add ${taskId} to current Session: ${cloudDataStoreCurrentSession}`);
const transaction = datastore.transaction();
const taskKey = datastore.key(['Session', cloudDataStoreCurrentSession]);
try {
await transaction.run();
const [task] = await transaction.get(taskKey);
let sessionTasks = task.session_tasks;
sessionTasks.push(taskId);
task.session_tasks = sessionTasks;
transaction.save({
key: taskKey,
data: task,
});
transaction.commit();
console.log(`Task ${taskId} added to current Session successfully.`);
} catch (err) {
console.error('ERROR:', err);
transaction.rollback();
}
}
taskId
是我要存储在名为 session_tasks
.
的 属性 数组中的另一个实体的字符串 ID
但它并没有走到那一步。在这一行之后:
const [task] = await transaction.get(taskKey);
错误是task
未定义:
ERROR: TypeError: Cannot read property 'session_tasks' of undefined
at pushTaskIdToCurrentSession
这段代码有什么显而易见的地方吗?
更新:
改用这个:
const task = await transaction.get(taskKey).catch(console.error);
给我一个任务对象,但它似乎是在数据存储上创建一个新实体:
我也遇到这个错误:
(node:19936) UnhandledPromiseRejectionWarning: Error: Unsupported field value, undefined, was provided.
at Object.encodeValue (/Users/.../node_modules/@google-cloud/datastore/build/src/entity.js:387:15)
这表明数组不受支持?
这里的问题是 Datastore 支持两种 ID。
- 以
name=
开头的ID是自定义ID。它们被视为字符串
- 以
id=
开头的 ID 是数字 auto-generated ID,并被视为整数
当您尝试更新数据存储中的值时,cloudDataStoreCurrentSession 被视为字符串。由于 Datastore 找不到已创建的具有该自定义名称的实体键,因此它创建了它并添加了 name=
以指定它是一个自定义名称。因此,您必须将 cloudDataStoreCurrentSession 作为整数传递才能正确保存数据。
如果我没理解错的话,您正在尝试使用特定的实体种类和实体键从数据存储加载字符串数组列表。然后您再添加一项任务并为特定的实体种类和实体键更新数据存储的值。
我创建了与您相同的案例场景,并自己编写了一些代码。在 this GitHub code 中,您会发现我的示例执行以下操作:
- 转到数据存储实体种类会话。
- 从实体键 id=5639456635748352 中检索所有数据(例如)。
- 从键中获取数组列表:session_tasks.
- 添加从函数参数传递的新任务。
- 对数据存储执行事务并更新值。
所有步骤都记录在代码中,并且有很多注释解释了代码的工作原理。还有两个 currentSessionID 的例子。一种用于自定义名称,另一种用于自动生成的 ID。您可以测试代码了解其用法并根据需要进行修改。
我在从 Google 数据存储中检索实体时遇到问题。这是我的代码:
async function pushTaskIdToCurrentSession(taskId){
console.log(`Attempting to add ${taskId} to current Session: ${cloudDataStoreCurrentSession}`);
const transaction = datastore.transaction();
const taskKey = datastore.key(['Session', cloudDataStoreCurrentSession]);
try {
await transaction.run();
const [task] = await transaction.get(taskKey);
let sessionTasks = task.session_tasks;
sessionTasks.push(taskId);
task.session_tasks = sessionTasks;
transaction.save({
key: taskKey,
data: task,
});
transaction.commit();
console.log(`Task ${taskId} added to current Session successfully.`);
} catch (err) {
console.error('ERROR:', err);
transaction.rollback();
}
}
taskId
是我要存储在名为 session_tasks
.
但它并没有走到那一步。在这一行之后:
const [task] = await transaction.get(taskKey);
错误是task
未定义:
ERROR: TypeError: Cannot read property 'session_tasks' of undefined
at pushTaskIdToCurrentSession
这段代码有什么显而易见的地方吗?
更新:
改用这个:
const task = await transaction.get(taskKey).catch(console.error);
给我一个任务对象,但它似乎是在数据存储上创建一个新实体:
我也遇到这个错误:
(node:19936) UnhandledPromiseRejectionWarning: Error: Unsupported field value, undefined, was provided.
at Object.encodeValue (/Users/.../node_modules/@google-cloud/datastore/build/src/entity.js:387:15)
这表明数组不受支持?
这里的问题是 Datastore 支持两种 ID。
- 以
name=
开头的ID是自定义ID。它们被视为字符串 - 以
id=
开头的 ID 是数字 auto-generated ID,并被视为整数
当您尝试更新数据存储中的值时,cloudDataStoreCurrentSession 被视为字符串。由于 Datastore 找不到已创建的具有该自定义名称的实体键,因此它创建了它并添加了 name=
以指定它是一个自定义名称。因此,您必须将 cloudDataStoreCurrentSession 作为整数传递才能正确保存数据。
如果我没理解错的话,您正在尝试使用特定的实体种类和实体键从数据存储加载字符串数组列表。然后您再添加一项任务并为特定的实体种类和实体键更新数据存储的值。
我创建了与您相同的案例场景,并自己编写了一些代码。在 this GitHub code 中,您会发现我的示例执行以下操作:
- 转到数据存储实体种类会话。
- 从实体键 id=5639456635748352 中检索所有数据(例如)。
- 从键中获取数组列表:session_tasks.
- 添加从函数参数传递的新任务。
- 对数据存储执行事务并更新值。
所有步骤都记录在代码中,并且有很多注释解释了代码的工作原理。还有两个 currentSessionID 的例子。一种用于自定义名称,另一种用于自动生成的 ID。您可以测试代码了解其用法并根据需要进行修改。