每分钟超出配额 API 个写入请求。 Node.js
Quota exceeded Sheets API write requests per minute. Node.js
我在使用 Google(使用 node.js)提供的表格 API 时遇到配额问题。我已经在使用批处理请求,并通过书面请求将我的写入配额增加到每分钟 900,但我仍然这个错误(解释后问题在底部):
我想做的是生成选定周数的体育联赛时间表(电子表格)。每周有 3 个独立的游戏(张)。用户首先只需选择多少周:
当用户单击“是”以确认计划时,无论所选金额是多少,都会创建电子表格:
每个电子表格都为 3 个不同的时间段创建了 3 个工作表,并将团队花名册数据复制到工作表中:
编辑 3: 我正在使用以下代码尝试生成这些电子表格:
// Create Result Sheets
exports.createGoogleResultsSheets = async (req,res) => {
console.log("createGoogleResultsSheets");
const season = req.body.teamData[0].stats[0].season;
// console.log(season);
const resultSeasonFolders = await getChildFiles(resultParentFolderID);
// console.log(resultSeasonFolders);
const exists = propertyExists(resultSeasonFolders,'name',season);
// Create season folder if it does not exist yet and get its id
let seasonResultsFolderId = null;
if (exists) {
// console.log("Season Exists");
const result = resultSeasonFolders.filter(folder=>folder.name == season).map(folder=>folder.id);
seasonResultsFolderId = result[0];
} else {
// console.log("Season does not exist");
// Create Season Folder
let fileMetadata = {
'name': season,
'mimeType': 'application/vnd.google-apps.folder',
'parents' : [resultParentFolderID]
};
const result = await drive.files.create({auth: jwtClient, resource: fileMetadata});
// console.log(result);
seasonResultsFolderId = result.data.id;
}
// console.log("Folder ID:");
// console.log(seasonResultsFolderId);
var i = 0;
for (const week of req.body.schedule) {
//console.log(util.inspect(week, false, null, true));
i++;
// create sheet for each week
let fileMetadata = {
'name': "Week-"+i,
'mimeType': 'application/vnd.google-apps.spreadsheet',
'parents' : [seasonResultsFolderId]
};
let result = await drive.files.create({auth: jwtClient, resource: fileMetadata});
let spreadsheetId = result.data.id;
for (const game of week) {
game.teamA.data.forEach(player => {
player.push(game.teamA.name);
});
game.teamB.data.forEach(player => {
player.push(game.teamB.name);
});
// Can't have sheet names containing : if we want to use .append()
let sheetName = game.time.toString().replace(':', '.').trim();
// add each game to weeks spreadsheet
await sheets.spreadsheets.batchUpdate ({
spreadsheetId : spreadsheetId,
resource: {requests: [
{addSheet: {properties: {title: sheetName }}}
]}
});
console.log("Spreadsheet Id:");
console.log(spreadsheetId);
// console.log(sheetName);
// let sheetId = await getSheetId(spreadsheetId,sheetName);
// // format cells
// let formatResources = {
// spreadsheetId: sheetId,
// resource: {
// requests: [
// {
// repeatCell: {
// range: {
// sheetId: sheetId,
// startRowIndex: 0,
// },
// cell: {
// userEnteredFormat: {
// textFormat: {
// bold: true,
// },
// },
// },
// fields: "userEnteredFormat.textFormat",
// },
// },
// ],
// },
// };
//await sheets.spreadsheets.batchUpdate(formatResources);
// add data to each game sheet
let resources = {
spreadsheetId: spreadsheetId,
resource:{
valueInputOption: "RAW",
data:[
{
range: "'" + sheetName + "'!A1:I1",
values: [['First','Last','Email','Position','Number','Team','Goals','Assists','Penalties']]
},
{
range: "'" + sheetName + "'!K1:L1",
values: [['Team','Shots']]
},
{
range: "'" + sheetName + "'!K2:L3",
values: [[game.teamA.data.name,''],[game.teamB.data.name,'']]
},
{
range: "'" + sheetName + "'!A2:F12",
values: game.teamA.data
},
{
range: "'" + sheetName + "'!A14:F24",
values: game.teamB.data
}
]
}
};
await sheets.spreadsheets.values.batchUpdate(resources);
}
// delete "Sheet1" (gid=0) from every spreadsheet
await sheets.spreadsheets.batchUpdate({
spreadsheetId: spreadsheetId,
resource: { requests: [
{deleteSheet : {sheetId :0}}
]}
});
}
};
注意: Google Sheets API/Service Details
顺便说一下,我并没有使用那么多写请求:
注 2: 而且我的配额限制增加了:
问题 1:我是否正确使用了 batchUpdates,或者我是否缺少可以进一步简化此代码的概念?
问题 2:我的计算是我对工作表 api 使用了 245 次写入调用,但是“API/Service 详细信息”控制台正在显示31. 我是不是遗漏了一些概念或以某种方式计算错误?我的配额怎么被超过了?嵌套的 5 个数组是单个 batchUpdate 还是 5 个 batchUpdate?如果后者适用,这将向工作表添加数百次写入调用 api。
API 写入计算:
创建 105 张(35 周 * 3 场比赛)
+105 次写入调用
给105个工作表中的每一个添加5个数据范围
+105 写入调用(或者这是 105 * 5 ?)
使用以下方法从所有 35 个工作表中删除“Sheet1”:
+35 次写入调用
编辑:根据要求,这是一周的样子(我缩短了 'data' 的长度,为了便于阅读,通常是 10 人。我还想指出我没有错误如果我选择 1 或 2 周而不是 35 周,则写这些范围。
week
:
[
{
teamA: {
data: [
[ 'Robert', 'Manning', 'robert.manning@email.com', 'C', '45' ],
[ 'Adrian', 'Martin', 'adrian.martin@email.com', 'RW', '5' ],
],
name: 'Green'
},
teamB: {
data: [
[ 'Isaac', 'Payne', 'isaac.payne@email.com', 'C', '11' ],
[ 'Alan', 'Lewis', 'alan.lewis@email.com', 'RW', '13' ],
],
name: 'Orange'
},
time: '4:30'
},
{
teamA: {
data: [
[ 'Stewart', 'Taylor', 'stewart.taylor@email.com', 'RW', '56' ],
[ 'Lucas', 'Davies', 'lucas.davies@email.com', 'RW', '85' ],
],
name: 'Yellow'
},
teamB: {
data: [
[ 'Dylan', 'Baker', 'dylan.baker@email.com', 'C', '11' ],
[ 'Edward', 'Dowd', 'edward.dowd@email.com', 'D', '65' ],
],
name: 'Black'
},
time: '6:00'
},
{
teamA: {
data: [
[ 'Gavin', 'Knox', 'gavin.knox@email.com', 'C', '45' ],
[ 'Paul', 'Wallace', 'paul.wallace@email.com', 'RW', '5' ],
],
name: 'Red'
},
teamB: {
data: [
['Andrew','Sanderson','andrew.sanderson@email.com','C','11'],
['Stewart','MacLeod','stewart.macleod@email.com','RW','13'],
],
name: 'Teal'
},
time: '7:30'
}
]
编辑 2:
我取出了一些代码以将问题的范围限制为 API 调用,因此省略了 sheetName
定义之类的内容,但这里是:
我相信你的目标如下。
- 您想通过修改脚本来减少表格 API 的请求数。
这样的话,下面的修改怎么样?
在这个修改中,for (const week of req.body.schedule) {,,,}
的循环中使用了2个API调用。
修改后的脚本:
for (const week of req.body.schedule) {
i++;
let fileMetadata = {
name: "Week-" + i,
mimeType: "application/vnd.google-apps.spreadsheet",
parents: [seasonResultsFolderId],
};
let result = await drive.files.create({auth: jwtClient, resource: fileMetadata});
let sheetId = result.data.id;
const sheetNames = week.map((game) =>
game.time.toString().replace(":", ".").trim()
);
// Add sheets and delete 1st tab.
await sheets.spreadsheets.batchUpdate({
spreadsheetId: sheetId,
resource: {
requests: [
...sheetNames.map((title) => ({
addSheet: {
properties: { title },
},
})),
{ deleteSheet: { sheetId: 0 } },
],
},
});
// Put values to each sheet.
const data = week.map((game, i) => {
game.teamA.data.forEach((player) => {
player.push(game.teamA.name);
});
game.teamB.data.forEach((player) => {
player.push(game.teamB.name);
});
return [
{
range: "'" + sheetNames[i] + "'!A1:I1",
values: [
[
"First",
"Last",
"Email",
"Position",
"Number",
"Team",
"Goals",
"Assists",
"Penalties",
],
],
},
{
range: "'" + sheetNames[i] + "'!K1:L1",
values: [["Team", "Shots"]],
},
{
range: "'" + sheetNames[i] + "'!K2:L3",
values: [
[game.teamA.name, ""],
[game.teamB.name, ""],
],
},
{
range: "'" + sheetNames[i] + "'!A2:F12",
values: game.teamA.data,
},
{
range: "'" + sheetNames[i] + "'!A14:F24",
values: game.teamB.data,
},
];
});
await sheets.spreadsheets.values.batchUpdate({
spreadsheetId: sheetId,
resource: { valueInputOption: "RAW", data },
});
}
- 在您的情况下,在方法:spreadsheets.batchUpdate 中,所有添加 sheet 和删除 sheet 的请求都可以包含在一个请求中。
- 在您的情况下,在方法:spreadsheets.values.batchUpdate 中,所有为每个 sheet 赋值的请求都可以包含在一个请求中。
注:
循环使用Sheets API时,可能会因为连续请求而出错。当此脚本为运行时,会出现这样的错误,请将等待的脚本放在循环中。
如果要减少DriveAPI的请求数,可以使用批量请求。 Ref
参考文献:
我在使用 Google(使用 node.js)提供的表格 API 时遇到配额问题。我已经在使用批处理请求,并通过书面请求将我的写入配额增加到每分钟 900,但我仍然这个错误(解释后问题在底部):
我想做的是生成选定周数的体育联赛时间表(电子表格)。每周有 3 个独立的游戏(张)。用户首先只需选择多少周:
当用户单击“是”以确认计划时,无论所选金额是多少,都会创建电子表格:
每个电子表格都为 3 个不同的时间段创建了 3 个工作表,并将团队花名册数据复制到工作表中:
编辑 3: 我正在使用以下代码尝试生成这些电子表格:
// Create Result Sheets
exports.createGoogleResultsSheets = async (req,res) => {
console.log("createGoogleResultsSheets");
const season = req.body.teamData[0].stats[0].season;
// console.log(season);
const resultSeasonFolders = await getChildFiles(resultParentFolderID);
// console.log(resultSeasonFolders);
const exists = propertyExists(resultSeasonFolders,'name',season);
// Create season folder if it does not exist yet and get its id
let seasonResultsFolderId = null;
if (exists) {
// console.log("Season Exists");
const result = resultSeasonFolders.filter(folder=>folder.name == season).map(folder=>folder.id);
seasonResultsFolderId = result[0];
} else {
// console.log("Season does not exist");
// Create Season Folder
let fileMetadata = {
'name': season,
'mimeType': 'application/vnd.google-apps.folder',
'parents' : [resultParentFolderID]
};
const result = await drive.files.create({auth: jwtClient, resource: fileMetadata});
// console.log(result);
seasonResultsFolderId = result.data.id;
}
// console.log("Folder ID:");
// console.log(seasonResultsFolderId);
var i = 0;
for (const week of req.body.schedule) {
//console.log(util.inspect(week, false, null, true));
i++;
// create sheet for each week
let fileMetadata = {
'name': "Week-"+i,
'mimeType': 'application/vnd.google-apps.spreadsheet',
'parents' : [seasonResultsFolderId]
};
let result = await drive.files.create({auth: jwtClient, resource: fileMetadata});
let spreadsheetId = result.data.id;
for (const game of week) {
game.teamA.data.forEach(player => {
player.push(game.teamA.name);
});
game.teamB.data.forEach(player => {
player.push(game.teamB.name);
});
// Can't have sheet names containing : if we want to use .append()
let sheetName = game.time.toString().replace(':', '.').trim();
// add each game to weeks spreadsheet
await sheets.spreadsheets.batchUpdate ({
spreadsheetId : spreadsheetId,
resource: {requests: [
{addSheet: {properties: {title: sheetName }}}
]}
});
console.log("Spreadsheet Id:");
console.log(spreadsheetId);
// console.log(sheetName);
// let sheetId = await getSheetId(spreadsheetId,sheetName);
// // format cells
// let formatResources = {
// spreadsheetId: sheetId,
// resource: {
// requests: [
// {
// repeatCell: {
// range: {
// sheetId: sheetId,
// startRowIndex: 0,
// },
// cell: {
// userEnteredFormat: {
// textFormat: {
// bold: true,
// },
// },
// },
// fields: "userEnteredFormat.textFormat",
// },
// },
// ],
// },
// };
//await sheets.spreadsheets.batchUpdate(formatResources);
// add data to each game sheet
let resources = {
spreadsheetId: spreadsheetId,
resource:{
valueInputOption: "RAW",
data:[
{
range: "'" + sheetName + "'!A1:I1",
values: [['First','Last','Email','Position','Number','Team','Goals','Assists','Penalties']]
},
{
range: "'" + sheetName + "'!K1:L1",
values: [['Team','Shots']]
},
{
range: "'" + sheetName + "'!K2:L3",
values: [[game.teamA.data.name,''],[game.teamB.data.name,'']]
},
{
range: "'" + sheetName + "'!A2:F12",
values: game.teamA.data
},
{
range: "'" + sheetName + "'!A14:F24",
values: game.teamB.data
}
]
}
};
await sheets.spreadsheets.values.batchUpdate(resources);
}
// delete "Sheet1" (gid=0) from every spreadsheet
await sheets.spreadsheets.batchUpdate({
spreadsheetId: spreadsheetId,
resource: { requests: [
{deleteSheet : {sheetId :0}}
]}
});
}
};
注意: Google Sheets API/Service Details
顺便说一下,我并没有使用那么多写请求:
注 2: 而且我的配额限制增加了:
问题 1:我是否正确使用了 batchUpdates,或者我是否缺少可以进一步简化此代码的概念?
问题 2:我的计算是我对工作表 api 使用了 245 次写入调用,但是“API/Service 详细信息”控制台正在显示31. 我是不是遗漏了一些概念或以某种方式计算错误?我的配额怎么被超过了?嵌套的 5 个数组是单个 batchUpdate 还是 5 个 batchUpdate?如果后者适用,这将向工作表添加数百次写入调用 api。
API 写入计算:
创建 105 张(35 周 * 3 场比赛) +105 次写入调用
给105个工作表中的每一个添加5个数据范围 +105 写入调用(或者这是 105 * 5 ?)
使用以下方法从所有 35 个工作表中删除“Sheet1”: +35 次写入调用
编辑:根据要求,这是一周的样子(我缩短了 'data' 的长度,为了便于阅读,通常是 10 人。我还想指出我没有错误如果我选择 1 或 2 周而不是 35 周,则写这些范围。
week
:
[
{
teamA: {
data: [
[ 'Robert', 'Manning', 'robert.manning@email.com', 'C', '45' ],
[ 'Adrian', 'Martin', 'adrian.martin@email.com', 'RW', '5' ],
],
name: 'Green'
},
teamB: {
data: [
[ 'Isaac', 'Payne', 'isaac.payne@email.com', 'C', '11' ],
[ 'Alan', 'Lewis', 'alan.lewis@email.com', 'RW', '13' ],
],
name: 'Orange'
},
time: '4:30'
},
{
teamA: {
data: [
[ 'Stewart', 'Taylor', 'stewart.taylor@email.com', 'RW', '56' ],
[ 'Lucas', 'Davies', 'lucas.davies@email.com', 'RW', '85' ],
],
name: 'Yellow'
},
teamB: {
data: [
[ 'Dylan', 'Baker', 'dylan.baker@email.com', 'C', '11' ],
[ 'Edward', 'Dowd', 'edward.dowd@email.com', 'D', '65' ],
],
name: 'Black'
},
time: '6:00'
},
{
teamA: {
data: [
[ 'Gavin', 'Knox', 'gavin.knox@email.com', 'C', '45' ],
[ 'Paul', 'Wallace', 'paul.wallace@email.com', 'RW', '5' ],
],
name: 'Red'
},
teamB: {
data: [
['Andrew','Sanderson','andrew.sanderson@email.com','C','11'],
['Stewart','MacLeod','stewart.macleod@email.com','RW','13'],
],
name: 'Teal'
},
time: '7:30'
}
]
编辑 2:
我取出了一些代码以将问题的范围限制为 API 调用,因此省略了 sheetName
定义之类的内容,但这里是:
我相信你的目标如下。
- 您想通过修改脚本来减少表格 API 的请求数。
这样的话,下面的修改怎么样?
在这个修改中,for (const week of req.body.schedule) {,,,}
的循环中使用了2个API调用。
修改后的脚本:
for (const week of req.body.schedule) {
i++;
let fileMetadata = {
name: "Week-" + i,
mimeType: "application/vnd.google-apps.spreadsheet",
parents: [seasonResultsFolderId],
};
let result = await drive.files.create({auth: jwtClient, resource: fileMetadata});
let sheetId = result.data.id;
const sheetNames = week.map((game) =>
game.time.toString().replace(":", ".").trim()
);
// Add sheets and delete 1st tab.
await sheets.spreadsheets.batchUpdate({
spreadsheetId: sheetId,
resource: {
requests: [
...sheetNames.map((title) => ({
addSheet: {
properties: { title },
},
})),
{ deleteSheet: { sheetId: 0 } },
],
},
});
// Put values to each sheet.
const data = week.map((game, i) => {
game.teamA.data.forEach((player) => {
player.push(game.teamA.name);
});
game.teamB.data.forEach((player) => {
player.push(game.teamB.name);
});
return [
{
range: "'" + sheetNames[i] + "'!A1:I1",
values: [
[
"First",
"Last",
"Email",
"Position",
"Number",
"Team",
"Goals",
"Assists",
"Penalties",
],
],
},
{
range: "'" + sheetNames[i] + "'!K1:L1",
values: [["Team", "Shots"]],
},
{
range: "'" + sheetNames[i] + "'!K2:L3",
values: [
[game.teamA.name, ""],
[game.teamB.name, ""],
],
},
{
range: "'" + sheetNames[i] + "'!A2:F12",
values: game.teamA.data,
},
{
range: "'" + sheetNames[i] + "'!A14:F24",
values: game.teamB.data,
},
];
});
await sheets.spreadsheets.values.batchUpdate({
spreadsheetId: sheetId,
resource: { valueInputOption: "RAW", data },
});
}
- 在您的情况下,在方法:spreadsheets.batchUpdate 中,所有添加 sheet 和删除 sheet 的请求都可以包含在一个请求中。
- 在您的情况下,在方法:spreadsheets.values.batchUpdate 中,所有为每个 sheet 赋值的请求都可以包含在一个请求中。
注:
循环使用Sheets API时,可能会因为连续请求而出错。当此脚本为运行时,会出现这样的错误,请将等待的脚本放在循环中。
如果要减少DriveAPI的请求数,可以使用批量请求。 Ref