Here is the improved template. I'd be interested if you think it is faster.
Code:
python:
def evaluate(book, context):
# Set these to what you want
field_name = 'authors'
value_in_note = 'a'
db = context.db.new_api
# check if we have already cached the notes
note_items = context.globals.get('items_with_notes', None)
if note_items is not None:
# We've already fetched which items have notes.
# Get the cached search result values
note_search_results = context.globals['note_search_results']
else:
# First time. Get the items with notes and initialize
# the search value cache.
note_items = db.get_all_items_that_have_notes(field_name)
context.globals['items_with_notes'] = note_items
note_search_results = {}
context.globals['note_search_results'] = note_search_results
# Check if this book is a match -- that the field has a note containing
# the desired text.
# We must first get the item_id for the value in the field to be checked.
field_value = book.get(field_name)
# if the field is multi-valued, use the first value
if isinstance(field_value, list):
field_value = field_value[0]
# Now get the internal ID of the value in field_name
item_id = db.get_item_id(field_name, field_value)
# Does the item have a note? If not, give up now.
if item_id not in note_items:
return ''
# The item has a note. Have we already checked it?
if item_id not in note_search_results:
# Item has a note but we haven't seen it before. Do the compare
# on the plain text version of the note.
result = ''
# Get the note.
note = db.notes_data_for(field_name, item_id)
if note:
# Get the plain text of the note.
note = note['searchable_text'].partition('\n')[2]
if note:
# use a case insensitive compare to check if the search value is in the note
from calibre.utils.icu import primary_contains
result = 'Yes' if primary_contains(value_in_note, note) else ''
# Cache the result of the comparison
note_search_results[item_id] = result
context.globals['note_search_results'] = note_search_results
# Return the cached value
return note_search_results.get(item_id, '')