Maybe; exported file contains notetype names that seems to be easy to find-and-replace to one where needed. I haven’t checked yet what would happen if I reimport it.
Trying the database way.
$ cd /sdcard/AnkiDroid
$ mkdir dbbackup
$ cp collection.anki2* dbbackup/
$ sqlite3 collection.anki2
sqlite> select id,name,mtime_secs from notetypes where name like '%plaintextimporter%' and name not like '%plaintextimporter_%' ;
1697472596652|com.ichi2.plaintextimporter|1697472596
A good candidate for the canonical notetype of this likeness.
sqlite> select count(*) from notetypes where name like '%plaintextimporter%' and id <> 1697472596652 ;
119
Number of notetypes to be remapped and deleted.
sqlite> select nt.id,count(*) n_notes from notetypes nt left join notes n on n.mid = nt.id where nt.name like '%plaintextimporter%' and nt.id <> 1697472596652 group by nt.id limit 5;
1451180286384|1932
1532351817741|35
1532352268554|1
1536153869241|53
1537957798184|30
Number of notes on some of the notetypes we marked for deletion.
sqlite> with target_note_ids as (select distinct n.id from notetypes nt left join notes n on n.mid = nt.id where nt.name like '%plaintextimporter%' and nt.id <> 1697472596652) select count(*) from target_note_ids;
7302
Number of notes we should remap.
sqlite> with target_note_ids as (select distinct n.id from notetypes nt left join notes n on n.mid = nt.id where nt.name like '%plaintextimporter%' and nt.id <> 1697472596652) update notes set mid=1697472596652 where id in (select id from target_note_ids);
sqlite> select changes();
7301
One row not updated for some reason, not sure why. Let’s ignore it.
sqlite> with target_note_ids as (select distinct n.id from notetypes nt left join notes n on n.mid = nt.id where nt.name like '%plaintextimporter%' and nt.id <> 1697472596652) select count(*) from target_note_ids;
1
Indeed only one note unremapped. After some minor debugging, looks like it’s just NULL
crept in due to slightly inaccurate query (left join
instead of join
for target_note_ids
).
sqlite> with target_note_ids as (select distinct n.id from notetypes nt join notes n on n.mid = nt.id where nt.name like '%plaintextimporter%' and nt.id <> 1697472596652) select count(*) from target_note_ids;
0
Now better.
Let’s remove unreferenced notetypes. First let’s count them.
sqlite> with used_notetype_ids as (select distinct mid from notes) select count(*) from used_notetype_ids;
21
sqlite> select count(*) from notetypes;
151
sqlite> select count(*) from notetypes where id not in (select distinct mid from notes);
130
It’s more than before because of there are other, unrelated abandoned notetypes.
sqlite> delete from notetypes where id not in (select distinct mid from notes);
Parse error: no such collation sequence: unicase
sqlite> .quit
Looks like Anki uses special things in SQLite. Published an sqlite3-loadable extension to handle this.
sqlite> .open /sdcard/AnkiDroid/collection.anki2
sqlite> .load ./libsqlite_unicase
sqlite> delete from notetypes where id not in (select distinct mid from notes);
sqlite> select changes();
130
sqlite> .quit
After loading AnkiDroid, everything seems to be OK. Database check did not found any error, now it shows “21 note types available”, with 7325 notes in com.ichi2.plaintextimporter
. Studing progress, starred notes, etc. are all preserved.