|
|
Thread Tools | Search this Thread |
10-14-2022, 11:53 AM | #1 |
Calibre Plugins Developer
Posts: 4,686
Karma: 2162246
Join Date: Oct 2010
Location: Australia
Device: Kindle Oasis
|
Is there a way to get author/tag/series/publisher ids+text within a virtual library?
In my Find Duplicates plugin, the main "Find Book Duplicates" functionality respects whatever virtual library search restriction you have applied.
EDIT: On further reading I can see that it uses self.gui.library_view.model() to operate within, and then only where it needs a more specific subset that it uses db.data.search_getting_ids() passing the restriction through. However the Metadata Variations duplicate check does *not* currently respect the virtual library selection. Looking at the code I wrote forever ago, it seems that for those searches I am invoking one of the following depending on user selection:
Is there an API equivalent I could use for these that could take a search_restriction argument? Or should I just iterate over the model to build up my own dictionaries? Last edited by kiwidude; 10-14-2022 at 12:02 PM. Reason: Found more info... |
10-14-2022, 11:59 AM | #2 |
creator of calibre
Posts: 44,546
Karma: 24495948
Join Date: Oct 2006
Location: Mumbai, India
Device: Various
|
Not sure what you are asking for exactly, but you first get the set of all book ids in the current virtual library. THen after that call
Code:
ans = set() for book_id in book_ids: ans |= {x for x in db.new_api.field_ids_for('tags', book_id)} |
10-14-2022, 12:16 PM | #3 | |
Calibre Plugins Developer
Posts: 4,686
Karma: 2162246
Join Date: Oct 2010
Location: Australia
Device: Kindle Oasis
|
Quote:
So it appears that indeed the answer is I need to iterate over all the books and build up my own (unique) sets... |
|
10-14-2022, 01:13 PM | #4 |
Grand Sorcerer
Posts: 12,029
Karma: 7257323
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
|
I think you want something like this ids_for_field() function. I don't know if the order is right. This produces (id, name) but you might want (name, id).
Code:
python: def ids_for_field(db, ids_of_books, field_name): # First get all the names for the desired books. # Use a set to make them unique unique_names = set() for tup in db.all_field_for(field_name, ids_of_books).values(): for vals in tup: unique_names.update((vals,)) # Now get the ids for the names and build the pairs id_field_pairs = list() for aut in unique_names: id_field_pairs.append((db.get_item_id(field_name, aut), aut)) return id_field_pairs def evaluate(book, context): db = context.db.new_api print('--------------------') # Get the list of books in the current VL ids_in_vl = db.search('', restriction='authors:a') # Get the id,val pairs for the desired field field_pairs = ids_for_field(db, ids_in_vl, 'authors') print(field_pairs) return '' |
10-14-2022, 01:29 PM | #5 |
Grand Sorcerer
Posts: 12,029
Karma: 7257323
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
|
Here is an example that uses the current VL
Code:
python: def ids_for_field(db, ids_of_books, field_name): # First get all the names for the desired books. # Use a set to make them unique unique_names = set() for tup in db.all_field_for(field_name, ids_of_books).values(): for val in tup: unique_names.add(val) # Now get the ids for the names and build the pairs id_field_pairs = list() for name in unique_names: id_field_pairs.append((db.get_item_id(field_name, name), name)) return id_field_pairs def evaluate(book, context): print('--------------------') # Get the list of books in the current VL ids_in_vl = context.db.data.search_getting_ids('', '', use_virtual_library=True) # Get the id,val pairs for the desired field field_pairs = ids_for_field(context.db.new_api, ids_in_vl, 'authors') print(field_pairs) return '' Last edited by chaley; 10-14-2022 at 01:44 PM. Reason: Small improvement to ids_for_field |
10-14-2022, 02:26 PM | #6 |
Calibre Plugins Developer
Posts: 4,686
Karma: 2162246
Join Date: Oct 2010
Location: Australia
Device: Kindle Oasis
|
Awesome, thanks chaley! That will save me much time in experimenting
|
10-14-2022, 05:24 PM | #7 |
Grand Sorcerer
Posts: 12,029
Karma: 7257323
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
|
Apologies for the churn. I looked at the underlying code for the API methods I used and found a significant inefficiency in what I proposed. The underlying reversed dictionary {id:name} was being generated for *every* field item. For big libraries this could be a significant performance hit.
Here is a version that reverses the id map once then uses it to build the output. Code:
def ids_for_field(db, ids_of_books, field_name): # First get all the names for the desired books. # Use a set to make them unique unique_names = set() for tup in db.all_field_for(field_name, ids_of_books).values(): for val in tup: unique_names.add(val) # reverse the map of ids to names so id_map[name] gives the id id_map = {v:k for k,v in db.get_id_map(field_name).items()} # Now build the pairs (id, name) id_field_pairs = list() for name in unique_names: id_field_pairs.append((id_map[name], name)) return id_field_pairs |
10-15-2022, 01:51 PM | #8 |
Calibre Plugins Developer
Posts: 4,686
Karma: 2162246
Join Date: Oct 2010
Location: Australia
Device: Kindle Oasis
|
Oh that one made a massive difference indeed on my local library - thanks chaley!
|
|
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
How to show books with only 1 tag? Dynamic tag or virtual library? | cd2013 | Calibre | 4 | 03-01-2019 07:41 PM |
Virtual library from list of title/author | melvinwinklie | Library Management | 3 | 12-30-2015 01:30 AM |
Creating a virtual library according how many books by author | mariaclaudia | Calibre | 5 | 06-04-2015 01:03 AM |
Library skips publisher, goes directly to author | kennyc | Writers' Corner | 5 | 08-05-2013 07:26 AM |
Creating a Library file w/Author, Title, Summary and tag info | asktheeightball | Calibre | 2 | 01-18-2010 11:28 AM |