# Add new notes / update existing notes

**URL:** <https://forums.ankiweb.net/t/add-new-notes-update-existing-notes/9126>\
**Category:** Development\
**Created:** [April 9, 2021, 6:36pm UTC](https://forums.ankiweb.net/t/add-new-notes-update-existing-notes/9126 "2021-04-09T18:36:24Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Leon0402](https://avatars.discourse-cdn.com/v4/letter/l/ccd318/32.png) [@Leon0402](https://forums.ankiweb.net/u/Leon0402)\
**Post date:** [April 9, 2021, 6:36pm UTC](https://forums.ankiweb.net/t/add-new-notes-update-existing-notes/9126/1 "2021-04-09T18:36:25Z")

</div>

Hi,

I wonder how I can add a new Note with an id or update an existing Note (in case the id is taken).

For a new Note I came up with something like:

```
deckId = 42
noteId = 42

notetype = self.col.models.byName("Basic")
note = self.col.new_note(notetype)
note.guid = str(noteId)
note["Front"] = "Question"
note["Back"] = "Answer
self.col.add_note(note, deckId)

```

Here I’m not quite sure if “guid” is correct. What is the best way to set an id?

For getting an existing Note I can probably use `get_note(self, id: NoteId) -> Note` and then `update_note(self, note: Note) -> OpChanges`.

The first functions fails though, if the note does not exist, therefore I need a way to check that.

So how can I:

- Give a Note an unique identifier?
- Know if a Note with some ID already exists?

Thanks in advance!

---

<div class="post-metadata">

**Author:** ![abdo](https://sea2.discourse-cdn.com/flex002/user_avatar/forums.ankiweb.net/abdo/32/654_2.png) [@abdo](https://forums.ankiweb.net/u/abdo)\
**Post date:** [April 9, 2021, 8:05pm UTC](https://forums.ankiweb.net/t/add-new-notes-update-existing-notes/9126/2 "2021-04-09T20:05:02Z")

</div>

> [@Leon0402](#):
>
> Give a Note an unique identifier?

Anki takes care of giving new notes unique IDs. Could you explain why you need to set it explicitly?

> [@Leon0402](#):
>
> Know if a Note with some ID already exists?

`get_note` throws the `anki.errors.NotFoundError` exception if a note with the given ID doesn’t exist.

> [@Leon0402](#):
>
> `note.guid = str(noteId)`

GUID is different from the note ID by the way. The note ID field is actually `note.id`.  
I guess the GUID is mainly intended for internal use by Anki when importing/exporting, and I’m not sure setting it manually is a good idea.

---

<div class="post-metadata">

**Author:** ![Leon0402](https://avatars.discourse-cdn.com/v4/letter/l/ccd318/32.png) [@Leon0402](https://forums.ankiweb.net/u/Leon0402)\
**Post date:** [April 9, 2021, 9:25pm UTC](https://forums.ankiweb.net/t/add-new-notes-update-existing-notes/9126/3 "2021-04-09T21:25:34Z")

</div>

> [@abdo](#):
>
> Anki takes care of giving new notes unique IDs. Could you explain why you need to set it explicitly

Because I write an extension for importing notes and I want to be able to reimport Flashcards.  
Currently I use the txt Importer and set the first field as my id.  
I guess that would be possible here to (although I‘m not sure how), but having some internal field would be even better!

> [@abdo](#):
>
> `get_note` throws the `anki.errors.NotFoundError` exception if a note with the given ID doesn’t exist.

I thought about that, but wasn‘t sure if that‘s the way this should be done. But I guess this depends on question 1 anyway (Can I set this id)

> [@abdo](#):
>
> The note ID field is actually `note.id` .

I couldn‘t set it though. Anki expected it to be 0? Not quite sure I understood how it works.

---

<div class="post-metadata">

**Author:** ![Leon0402](https://avatars.discourse-cdn.com/v4/letter/l/ccd318/32.png) [@Leon0402](https://forums.ankiweb.net/u/Leon0402)\
**Post date:** [April 10, 2021, 5:52am UTC](https://forums.ankiweb.net/t/add-new-notes-update-existing-notes/9126/4 "2021-04-10T05:52:50Z")

</div>

Btw. I‘m using the latest master as it seems some useful functions has beend added quite recently.  
Just in case that matters.

---

<div class="post-metadata">

**Author:** ![dae](https://sea2.discourse-cdn.com/flex002/user_avatar/forums.ankiweb.net/dae/32/65_2.png) [@dae](https://forums.ankiweb.net/u/dae)\
**Post date:** [April 13, 2021, 1:35pm UTC](https://forums.ankiweb.net/t/add-new-notes-update-existing-notes/9126/5 "2021-04-13T13:35:30Z")

</div>

The import/export code is one of the remaining things that is in need of a refactor. You can set an arbitrary GUID if you need to keep track of a given note for now, but you’ll need to manually query the DB for find a note with a given GUID, and you may find it easier just to store the ID in a field instead.

---

<div class="post-metadata">

**Author:** ![Leon0402](https://avatars.discourse-cdn.com/v4/letter/l/ccd318/32.png) [@Leon0402](https://forums.ankiweb.net/u/Leon0402)\
**Post date:** [April 13, 2021, 4:54pm UTC](https://forums.ankiweb.net/t/add-new-notes-update-existing-notes/9126/6 "2021-04-13T16:54:16Z")

</div>

> [@dae](#):
>
> and you may find it easier just to store the ID in a field instead.

Is this detection for creating a new note or updating it when first field matches built into Note? Or how would I create / update the card with the provided functions in collection?

---

<div class="post-metadata">

**Author:** ![dae](https://sea2.discourse-cdn.com/flex002/user_avatar/forums.ankiweb.net/dae/32/65_2.png) [@dae](https://forums.ankiweb.net/u/dae)\
**Post date:** [April 14, 2021, 12:33am UTC](https://forums.ankiweb.net/t/add-new-notes-update-existing-notes/9126/7 "2021-04-14T00:33:42Z")

</div>

You can see how addcards.py does it for individual notes

---

<div class="post-metadata">

**Author:** ![Leon0402](https://avatars.discourse-cdn.com/v4/letter/l/ccd318/32.png) [@Leon0402](https://forums.ankiweb.net/u/Leon0402)\
**Post date:** [April 22, 2021, 6:17pm UTC](https://forums.ankiweb.net/t/add-new-notes-update-existing-notes/9126/8 "2021-04-22T18:17:48Z")

</div>

Thanks for the hint!

Based on what I found, I came up with this:

```auto
note = self.col.new_note(notetype)
... 
if note.duplicate_or_empty() == DuplicateOrEmptyResult.DUPLICATE:
  note.id = self.col.find_notes(self.col.build_search_string(note["id"], SearchNode(field_name="id")))[0]
  self.col.update_note(note)
else: 
  self.col.add_note(note, deckId)

```

There is one problem with this though. It seems like the deck information is lost after using update\_note(). When I update the notes, they all land in the default deck rather than the deck where they were before. Is this intentional? What can I do against this?

There is also a strange thing I noticed with NoteTypes. When I change the NoteType by adding new fields / replacing fields with those [anki/models.py at 42a4d11416d6b04e49cc05d9d2b7db9f8e19b1d8 · ankitects/anki · GitHub](https://github.com/ankitects/anki/blob/42a4d11416d6b04e49cc05d9d2b7db9f8e19b1d8/pylib/anki/models.py#L312), the ordinal number is not set.  
This causes duplicate\_or\_empty() to fail.

My workaround:

```auto
    def _addField(self, notetype, name: str):
        field = self.col.models.new_field(name)
        field["ord"] = len(notetype["flds"])
        self.col.models.add_field(notetype, field)

```

Furthermore I wonder why that matters at all to `duplicate_or_empty()`. This should just compare the note and not the notetype. The issue is also just with these ordinal numers for fields. Based on my tests, there is no problem with adding new fields (as long as they get an ordinal number as well) and also no problem with templates (which sets ordinal number to None as well).

---

<div class="post-metadata">

**Author:** ![dae](https://sea2.discourse-cdn.com/flex002/user_avatar/forums.ankiweb.net/dae/32/65_2.png) [@dae](https://forums.ankiweb.net/u/dae)\
**Post date:** [April 23, 2021, 6:38am UTC](https://forums.ankiweb.net/t/add-new-notes-update-existing-notes/9126/9 "2021-04-23T06:38:17Z")

</div>

You should not be setting the ordinals manually, you should save() the notetype and then load it again to get the assigned values if you’re planning to add material immediately afterwards. Manually assigning an id also looks wrong; you should load the existing note instead of assigning its id to a different note object.

---

<div class="post-metadata">

**Author:** ![Leon0402](https://avatars.discourse-cdn.com/v4/letter/l/ccd318/32.png) [@Leon0402](https://forums.ankiweb.net/u/Leon0402)\
**Post date:** [April 23, 2021, 7:00am UTC](https://forums.ankiweb.net/t/add-new-notes-update-existing-notes/9126/10 "2021-04-23T07:00:18Z")

</div>

> [@dae](#):
>
> You should not be setting the ordinals manually, you should save() the notetype and then load it again to get the assigned values if you’re planning to add material immediately afterwards

This is what I did originally. The problem is that when I change a notetype, it causes ` duplicate_or_empty` to return 0 for existing cards.

A simple example. Say I have a Notetype “MyCustomNoteType”. So I do retrieve it:

```auto
notetype = self.col.models.byName("MyCustomNoteType")

```

Then I try to detect if a Note already exists, so I construct a Note Object with an id as the first field

```auto
note = self.col.new_note(notetype)
note["id"] = "This is the first field and a note with such field exists"

```

I detect a change:

```auto
if note.duplicate_or_empty() == DuplicateOrEmptyResult.DUPLICATE:
  print("Note exists")

```

So far this works. But If I change the Nottype in certain ways, it causes duplicte\_or\_empty() to return 0, so no duplicate.  
What I can do:

```auto
notetype["tmpls"] = [] 
self.col.models.add_template(notetype, self.col.models.new_template("Card 1"))
self.col.models.save(notetype)

```

So remove all templates and add exact the same templates. It works.

What I can’t do

```auto
notetype["flds"] = [] 
field = self.col.models.new_field("id")
self.col.models.add_field(notetype, field)
self.col.models.save(notetype)

```

So removing all fields and adding exact the same fields.

So I try to search what the difference is: The ordinal numbers are None

But in general: I don’t understand what the notetype has to do with `duplicate_or_empty` for the note. If the note doesn’t change (same fields, same values, same id in first field, same notetype Id) that function should return duplicate. If the Notetype gets a new field and the note gets a new field, it should still be a duplicate, because the first field matches.

I figure I might just wanna search myself for this. So something like:

```auto
noteIds = self.col.find_notes(self.col.build_search_string("Here my duplicate id", SearchNode(field_name="id")))
if noteIds == []: 
  print("No Duplicate")
else 
  print("Duplicate")

```

Edit: Turns out this doesn’t work either when I modify the notetype in any way.

> [@dae](#):
>
> Manually assigning an id also looks wrong; you should load the existing note instead of assigning its id to a different note object.

I think you’re right. I thought as I constructed the note Id with all fields before, I could just copy the id over. But obviously there are more fields like the usn. So yes I should load the original note and modify that.  
I’ll see if that also fixes my issue.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex002/uploads/anki2/original/1X/8f1279ababc5879d54e4838989f606cfe55af8c7.jpeg) [@system](https://forums.ankiweb.net/u/system)\
**Post date:** [May 1, 2023, 3:18am UTC](https://forums.ankiweb.net/t/add-new-notes-update-existing-notes/9126/11 "2023-05-01T03:18:40Z")

</div>


