Find & Replace JavaScript Batch Editing PARTIAL Item Field Info

I'm looking for a way to batch edit one item field across many items that doesn't just delete or overwrite the item field value completely.

I have Zutilo and have made significant use of that, but there wasn't a way to overwrite a single item field to be a blank value — for example, removing the "language" item field value for all items to be blank. From the previous forum posts and this page, I figured out how to do that easily though.

https://www.zotero.org/support/dev/client_coding/javascript_api#batch_editing

Now I'm trying to figure out how to replace just one element of the item field value.

For example:
• For items with dates containing "-", replace "-" with "/", retaining the other item field value information
• For items with DOI starting with "10/", remove "10/" (replace "10/" with ""), retaining the remainder of the item field value
• For items with page numbers not containing "-", add "Article #" at the beginning of the item field value

The first part, the "search", is easy. It's an example script for "replace" or "insert" without overwriting the entire item field value which is what I want.

I'm not well-versed in coding but I'm pretty good at figuring things out and messing around with stuff, so I tried looking through some of the code of a few of the plugins I am using to see if I could find anything that would help me understand what needed to be edited in the Batch Editing example to make this work, but I haven't been able to figure it out — or even discern if it's possible in a simple enough way.

Hoping someone can point me in the right direction! TIA!

P.S. I don't need feedback on whether you personally believe this is a valuable or necessary function. For dates, I understand that they are all stored internally in the same format, but I like them to look the same for my own mental processing. For the second example, short DOIs don't actually really need to include the "10/" lead-in to the short DOI in the URL itself, but Zotero doesn't wipe those three characters when it adds the https://doi.org/ at the end of the citation. Please don't argue with me about whether I am managing my library "correctly".



  • edited November 13, 2022
    For items with dates containing "-", replace "-" with "/", retaining the other item field value information
    You'd use replace() with regular expressions. E.g., newValue.replace(/-/g, '/') to replace hyphens with slashes. You can try out single lines like "2004-12-12".replace(/-/g, '/') to test it.

    You should temporarily disable auto-sync and make sure you have a backup of your database before doing anything.
    Please don't argue with me about whether I am managing my library "correctly".
    You can obviously do what you want with your library, but just to be clear, the DOI field is meant to have an actual, non-short DOI in it, and if you store something else you'll prevent some functionality from working — e.g., you won't get retraction notifications.
  • Thanks for the speedy reply!

    Additional related question: What's the deal with the Field Modes for Dates? I saw the documentation about the Field Modes for Creators (https://www.zotero.org/support/dev/client_coding/javascript_api#examplecreator_name_changes) and thought there might be a similar way to adjust the way the dates show up — I use the Windows desktop app so it's not uniform — but I can't find any information about whether that is true, and if so, how they are defined.

    Thanks for that info on the retraction notifications. I wasn't aware and it's good to keep in mind, but I'm not in a particularly scientific field and retractions are not a big concern. Minimizing the character count of my citations is a much higher priority for me at the moment.



    With a fair bit of trial and error, I figured out the replace function. I'm adding a few of the variations I came up with here for anyone else looking to do anything similar. It's probably not the best way to do these, but this is truly not my domain. I'm an architect (like literal buildings, nothing technical/computer related) and disability studies scholar. I really just winged it.

    Also, for anyone else who isn't super familiar with this but is going to play around — besides backing up the database and disabling auto-sync, I also made a temporary dummy library with just a couple dozen items to mess with so I really didn't have to think about it.



    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    REPLACE PART IN FIELD VALUE (FOR ONE ITEM FIELD ACROSS ALL LIBRARY ITEMS)
    ━━━━━━━━━━━━━━━
    This will apply to the entire library. You need to adjust the search conditions if you don't want to clear the defined category for every single item.
    Example: fieldName = "date"; oldPart = /-/g; newPart = "/";
    ━━━━━━━━━━━━━━━
    var fieldName = "■";
    var oldPart = /■/g;
    var newPart = "■";

    let s = new Zotero.Search();
    s.libraryID = ZoteroPane.getSelectedLibraryID();
    s.addCondition(fieldName, "isNot", "");
    let ids = await s.search();
    if (!ids.length) {
    return "No items found";
    }
    await Zotero.DB.executeTransaction(async function () {
    for (let id of ids) {
    let item = await Zotero.Items.getAsync(id);
    let oldWhole = item.getField(fieldName);
    let newWhole = oldWhole.replace(oldPart, newPart);
    item.setField(fieldName, newWhole);
    await item.save();
    }
    });
    return ids.length + " item(s) updated";
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━



    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    CLEAR FIELD VALUE (FOR ONE ITEM FIELD ACROSS ALL LIBRARY ITEMS)
    ━━━━━━━━━━━━━━━
    This will apply to the entire library. You need to adjust the search conditions if you don't want to clear the defined category for every single item. For example, I like the "language" field to be cleared on every single item because it's irrelevant information to me and the less clutter the better. In this same example, if you wanted to only clear an item's language field value if it was English, you could adjust the conditions:
    s.addCondition(fieldName, "contains", "en");
    ━━━━━━━━━━━━━━━
    var fieldName = "■";

    let newValue = "";
    let fieldID = Zotero.ItemFields.getID(fieldName);
    let s = new Zotero.Search();
    s.libraryID = ZoteroPane.getSelectedLibraryID();
    s.addCondition(fieldName, "isNot", "");
    let ids = await s.search();
    if (!ids.length) {
    return "No items found";
    }
    await Zotero.DB.executeTransaction(async function () {
    for (let id of ids) {
    let item = await Zotero.Items.getAsync(id);
    item.setField(fieldName, newValue);
    await item.save();
    }
    });
    return ids.length + " item(s) updated";
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━



    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    REMOVE "10/" FROM THE FRONT OF (SHORT) DOI
    ━━━━━━━━━━━━━━━
    I previously shortened using the Zotero DOI Manager plug-in (https://github.com/bwiernik/zotero-shortdoi). However, the "10/" opener isn't actually necessary in the short-DOI URL. Removing the "10/" will cause the plug-in to categorize them as invalid, but they are fine. And it's just as easy to add the "10/" all back in as it is to remove them all at once like this. With the plug-in you are also able to then revert them all back to long-DOIs easily, should you ever need to.
    ━━━━━━━━━━━━━━━
    var fieldName = "DOI";

    let s = new Zotero.Search();
    s.libraryID = ZoteroPane.getSelectedLibraryID();
    s.addCondition("DOI", "beginsWith", "10/");
    let ids = await s.search();
    if (!ids.length) {
    return "No items found";
    }
    await Zotero.DB.executeTransaction(async function () {
    for (let id of ids) {
    let item = await Zotero.Items.getAsync(id);
    let oldWhole = item.getField(fieldName);
    let newWhole = oldWhole.replace("10/", "");
    item.setField(fieldName, newWhole);
    await item.save();
    }
    });
    return ids.length + " item(s) updated";
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━



    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    ADD "Article #" TO START OF PAGES
    ━━━━━━━━━━━━━━━
    Example of a more complex search condition. Many items import into Zotero and only show a single page number, which is often the page *count*. When I go through and correct these, I use "." after the number to indicate it is a single page and that is the correct page number; "+" after the number to indicate that is the first page but I don't have access to how many pages/full range that the original published piece was; ";" for items that are on multiple non-consecutive pages (as print newspaper articles often are); and "Article #" before the number for the publications that have transitioned to using Article IDs instead of page numbers. The "." will not appear in your citations. Including "Article #" is not really proper citation, but it is completely acceptable for my purposes.
    ━━━━━━━━━━━━━━━
    var fieldName = "pages";
    var newPart = "Article #";

    let oldPart = "";
    let s = new Zotero.Search();
    s.libraryID = ZoteroPane.getSelectedLibraryID();
    s.addCondition(fieldName, "contains", "");
    s.addCondition(fieldName, "doesNotContain", ".");
    s.addCondition(fieldName, "doesNotContain", "+");
    s.addCondition(fieldName, "doesNotContain", "#");
    s.addCondition(fieldName, "doesNotContain", "–");
    s.addCondition(fieldName, "doesNotContain", ";");
    let ids = await s.search();
    if (!ids.length) {
    return "No items found";
    }
    await Zotero.DB.executeTransaction(async function () {
    for (let id of ids) {
    let item = await Zotero.Items.getAsync(id);
    let oldWhole = item.getField(fieldName);
    let newWhole = oldWhole.replace(oldPart, newPart);
    item.setField(fieldName, newWhole);
    await item.save();
    }
    });
    return ids.length + " item(s) updated";
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  • Thanks for that info on the retraction notifications. I wasn't aware and it's good to keep in mind, but I'm not in a particularly scientific field and retractions are not a big concern. Minimizing the character count of my citations is a much higher priority for me at the moment.
    Just to be clear, retraction notifications are just one example. DOIs also used within Zotero for duplicate detection, they'll be used in an upcoming update to automatically update item metadata, and they'll be used for various other things going forward — any time an existing item needs to be uniquely identified. You're breaking all of that by replacing them. (Note that this applies to any form of ShortDOI, not just without the "10/".)

    Standard DOIs these days are rarely the sort of absurdly long strings with parentheses that some early DOIs were, so it's just not saving that much space, which is why ShortDOIs have mostly fallen out of favor.
  • Yep, got it, thanks. I understand it's not the best move for most people, but it is necessary for me at the moment. The space savings is actually very substantial for some things I am working on. I checked that the conversion back to long-DOI isn't a headache if/when I ever want to.

    So is there no documentation regarding the field mode for dates?
  • Field mode is a creator thing. Nothing to do with dates. Both JavaScript and Zotero have various things to format dates, but that's not something I can help with at the moment.
Sign In or Register to comment.