Skip to content

Commit

Permalink
performance: save all fields of an item at once instead of each field…
Browse files Browse the repository at this point in the history
… separately
  • Loading branch information
northword committed Dec 13, 2023
1 parent 38d2701 commit 85fa54e
Show file tree
Hide file tree
Showing 12 changed files with 61 additions and 44 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Performance

- 对一个条目执行更新时,一次性保存所有字段,而不是每个字段分别保存一次。/ When updating an item, save all fields at once instead of saving each field separately.

## [1.6.15] - 2023-12-13

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion src/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ async function onUpdateInBatch(mode: string, items: Zotero.Item[] | "item" | "co
}
}

let processor: ((...args: any[]) => Promise<void> | void) | undefined = undefined,
let processor: ((...args: any[]) => Promise<Zotero.Item | void> | Zotero.Item | void) | undefined = undefined,
args: any[] = [];

switch (mode) {
Expand Down
34 changes: 19 additions & 15 deletions src/modules/formatMetadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,24 @@ export default class FormatMetadata {
@callingLoggerForMethod
static async updateStdFlow(item: Zotero.Item) {
// 作者、期刊、年、期、卷、页 -> 判断语言 -> 作者大小写 -> 匹配缩写 -> 匹配地点 -> 格式化日期 -> 格式化DOI
getPref("isEnableOtherFields") ? await this.updateMetadataByIdentifier(item) : "skip";
getPref("isEnableLang") ? await this.updateLanguage(item) : "skip";
getPref("isEnableCreators") ? await this.capitalizeName(item) : "skip";
getPref("isEnableTitleCase") ? await this.titleCase2SentenceCase(item) : "skip";
getPref("isEnablePublicationTitle") ? await this.updatePublicationTitle(item) : "skip";
getPref("isEnableAbbr") ? await this.updateJournalAbbr(item) : "skip";
getPref("isEnablePlace") ? await this.updateUniversityPlace(item) : "skip";
getPref("isEnableDateISO") && !getPref("isEnableOtherFields") ? await this.updateDate(item) : "skip";
getPref("isEnableDOI") ? await this.updateDOI(item) : "skip";
item = getPref("isEnableOtherFields") ? await this.updateMetadataByIdentifier(item) : item;
item = getPref("isEnableLang") ? await this.updateLanguage(item) : item;
item = getPref("isEnableCreators") ? await this.capitalizeName(item) : item;
item = getPref("isEnableTitleCase") ? await this.titleCase2SentenceCase(item) : item;
item = getPref("isEnablePublicationTitle") ? await this.updatePublicationTitle(item) : item;
item = getPref("isEnableAbbr") ? await this.updateJournalAbbr(item) : item;
item = getPref("isEnablePlace") ? await this.updateUniversityPlace(item) : item;
item = getPref("isEnableDateISO") && !getPref("isEnableOtherFields") ? await this.updateDate(item) : item;
item = getPref("isEnableDOI") ? await this.updateDOI(item) : item;
return item;
}

@callingLoggerForMethod
static async updateNewItem(item: Zotero.Item) {
this.checkWebpage(item);
getPref("isEnableCheckDuplication") ? this.checkDuplication(item) : "skip";
getPref("add.update") ? await this.updateStdFlow(item) : "";
item = getPref("add.update") ? await this.updateStdFlow(item) : item;
return item;
}

/**
Expand All @@ -83,11 +85,12 @@ export default class FormatMetadata {
*/
public static async setFieldValue(item: Zotero.Item, field: Zotero.Item.ItemField, value: any) {
if (value == undefined) {
return;
return item;
} else {
item.setField(field, value);
await item.saveTx();
// await item.saveTx();
}
return item;
}

static test(item: Zotero.Item) {
Expand All @@ -113,21 +116,22 @@ function updateOnItemAdd(items: Zotero.Item[]) {
async function run(
item: Zotero.Item,
task: {
processor: (...args: any[]) => Promise<void> | void;
processor: (...args: any[]) => Promise<Zotero.Item | void> | Zotero.Item | void;
args: any[];
// this?: any;)
},
) {
// todo: 将所有格式化字段函数都返回 item,统一保存一次,避免多次 SQL,提高效率。
const args = [item, ...task.args];
// await task.processor.apply(task.this, args);
await task.processor(...args);
item = (await task.processor(...args)) ?? item;
item.saveTx();
}

async function runInBatch(
items: Zotero.Item[],
task: {
processor: (...args: any[]) => Promise<void> | void;
processor: (...args: any[]) => Promise<Zotero.Item | void> | Zotero.Item | void;
args: any[];
},
) {
Expand Down
3 changes: 2 additions & 1 deletion src/modules/rules/field-creators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ async function capitalizeName(item: Zotero.Item) {
newCreators.push(creator);
}
item.setCreators(newCreators);
await item.saveTx();
return item;
// await item.saveTx();
}

// todo: 期刊文章必须含有作者
3 changes: 2 additions & 1 deletion src/modules/rules/field-date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ export async function updateDate(item: Zotero.Item) {
const oldDate = item.getField("date") as string,
newDate = Zotero.Date.strToISO(oldDate);
newDate ? item.setField("date", newDate) : "";
await item.saveTx();
return item;
// await item.saveTx();
}
9 changes: 5 additions & 4 deletions src/modules/rules/field-journalAbbr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ export { updateJournalAbbr };
*
* @param item
*/
async function updateJournalAbbr(item: Zotero.Item) {
async function updateJournalAbbr(item: Zotero.Item): Promise<Zotero.Item> {
// 非 journalArticle 和 conferencePaper 直接跳过
if (item.itemType !== "journalArticle" && item.itemType !== "conferencePaper") {
ztoolkit.log(`[Abbr] Item type ${item.itemType} is not journalArticle or conferencePaper, skip it.`);
return;
return item;
}
// 无期刊全称直接跳过
const publicationTitle = item.getField("publicationTitle") as string;
if (publicationTitle == "") return;
if (publicationTitle == "") return item;
let journalAbbr = "";

// 从自定义数据集获取
Expand Down Expand Up @@ -78,7 +78,8 @@ async function updateJournalAbbr(item: Zotero.Item) {
}

item.setField("journalAbbreviation", journalAbbr);
await item.saveTx();
return item;
// await item.saveTx();
}

/**
Expand Down
5 changes: 3 additions & 2 deletions src/modules/rules/field-language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async function updateLanguage(item: Zotero.Item) {
// WIP: 已有合法 ISO 639 - ISO 3166 代码的,不予处理
if (verifyIso3166(item.getField("language") as string) && getPref("lang.verifyBefore")) {
ztoolkit.log("[lang] The item has been skipped due to the presence of valid ISO 639 - ISO 3166 code.");
return;
return item;
}
const title = item.getField("title") as string;
const languageISO639_3 = getTextLanguage(title);
Expand All @@ -27,11 +27,12 @@ async function updateLanguage(item: Zotero.Item) {
progressWindow(`${title} error, franc return ${languageISO639_3}, to ${language}`, "failed");
} else {
item.setField("language", language);
await item.saveTx();
// await item.saveTx();
}
} else {
progressWindow(`Failed to identify the language of text “${title}”`, "failed");
}
return item;
}

/**
Expand Down
7 changes: 4 additions & 3 deletions src/modules/rules/field-misc.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
export async function updateDOI(item: Zotero.Item) {
const doi = item.getField("DOI");
if (doi && typeof doi == "string") {
const doiCleand = Zotero.Utilities.cleanDOI(doi);
doiCleand ? item.setField("DOI", doiCleand) : "pass";
const cleandDOI = Zotero.Utilities.cleanDOI(doi);
cleandDOI ? item.setField("DOI", cleandDOI) : "pass";
}
await item.saveTx();
return item;
// await item.saveTx();
}
13 changes: 5 additions & 8 deletions src/modules/rules/field-place.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,14 @@ export { updateUniversityPlace };

async function updateUniversityPlace(item: Zotero.Item) {
if (item.itemType == "thesis") {
try {
const university = item.getField("university") as string;
const place = getUniversityPlace(university);
item.setField("place", place);
await item.saveTx();
} catch (error) {
ztoolkit.log("失败", error);
}
const university = item.getField("university") as string;
const place = getUniversityPlace(university);
item.setField("place", place);
// await item.saveTx();
} else {
ztoolkit.log(`[Place] Item type ${item.itemType} is not thesis, skip it.`);
}
return item;
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/modules/rules/field-publication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ async function updatePublicationTitle(item: Zotero.Item) {
newPublicationTitle = publicationTitle;
}
item.setField("publicationTitle", newPublicationTitle);
await item.saveTx();
return item;
// await item.saveTx();
}

const skipWordsForPublicationTitle = [
Expand Down
7 changes: 4 additions & 3 deletions src/modules/rules/field-retrive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ async function updateMetadataByIdentifier(
// todo: 弹出 DOI 输入对话框?
if (!doi) {
progressWindow(getString("info-noDOI"), "fail");
return;
return item;
}

if (doi.match(/arxiv/gi)) {
Expand Down Expand Up @@ -135,8 +135,9 @@ async function updateMetadataByIdentifier(
// todo: 处理与标准格式化流程中空白字段填充的死循环
// needLint = (getPref("lintAfterRetriveByDOI") as boolean) ?? false;
// needLint ? await addon.hooks.onUpdateInBatch("std", [item]) : "skip";
await item.saveTx();
await Zotero.Promise.delay(1000);
return item;
// await item.saveTx();
// await Zotero.Promise.delay(1000);
}

async function getDOIFromArxiv(arxivID: string) {
Expand Down
15 changes: 10 additions & 5 deletions src/modules/rules/field-title.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ async function titleCase2SentenceCase(item: Zotero.Item) {
const title = item.getField("title", false, true) as string;
const newTitle = toSentenceCase(title);
item.setField("title", newTitle);
await item.saveTx();
return item;
// await item.saveTx();
}

/**
Expand All @@ -46,7 +47,8 @@ async function replaceGuillemetToBrackets(item: Zotero.Item) {
const title = item.getField("title", false, true) as string;
const newTitle = title.replace(//g, "〈").replace(//g, "〉");
item.setField("title", newTitle);
await item.saveTx();
return item;
// await item.saveTx();
}

/**
Expand All @@ -58,7 +60,8 @@ async function replaceBracketsToGuillemet(item: Zotero.Item) {
// const newTitle = title.replace(/<(?!\/|sub|sup|b|i)/g, "《").replace(/(?<!\/|sub|sup|b|i)>/g, "》");
const newTitle = title.replace(//g, "《").replace(//g, "》");
item.setField("title", newTitle);
await item.saveTx();
return item;
// await item.saveTx();
}

/**
Expand All @@ -70,7 +73,8 @@ async function replaceDoubleQuoteToSingleQuote(item: Zotero.Item) {
const title = item.getField("title") as string;
const newTitle = title.replace(/"/g, "'").replace(//g, "‘").replace(//g, "’");
item.setField("title", newTitle);
await item.saveTx();
return item;
// await item.saveTx();
}

/**
Expand All @@ -82,5 +86,6 @@ async function replaceSingleQuoteToDoubleQuote(item: Zotero.Item) {
const title = item.getField("title") as string;
const newTitle = title.replace(/'/g, '"').replace(//g, "“").replace(//g, "”");
item.setField("title", newTitle);
await item.saveTx();
return item;
// await item.saveTx();
}

0 comments on commit 85fa54e

Please sign in to comment.