docs: def find_by_keyword(self, keywords="", strict_match=False, book=-1):
          self.fyi("find_by_keyword, ... book=%s" % book)
          '''Search notes for a given keyword'''
          self.fyi("nota.find_by_keyword() with keywords %s; book=%s" % (keywords, book))
          keywordsKnown = []
          if not strict_match:
              keywords[0] = keywords[0].lower()
          for k in self.cur.execute("SELECT keyword FROM keyword;").fetchall():
              if strict_match:
                  keywordsKnown.extend(k)
              else:
                  keywordsKnown.extend(k)
                  keywordsKnown.extend([str(k[0]).lower()])
          self.fyi("keywordsKnown: %s" % keywordsKnown)
          # FIXME: only using first keyword here!
          if not strict_match:
              keywords_partial = []
              kl = len(keywords[0])
              if kl > 3:
                  for K in keywordsKnown:
                      if K[0:kl] == keywords[0]:
                          if K not in keywords_partial:
                              keywords_partial.append(K)
              # Try fuzzy search only if no direct matches
              keywords_fuzzy = []
              if not len(keywords_partial):
                  keywords_fuzzy = difflib.get_close_matches(keywords[0], keywordsKnown, n=1, cutoff=0.6)
              self.fyi("  keywords_partial %s" % keywords_partial)
              self.fyi("  keywords_fuzzy %s" % keywords_fuzzy)
              keywords = list(set(keywords_partial + keywords_fuzzy))
          self.fyi("nota.find_by_keyword() later, keywords: %s" % keywords)
          noteIds = []
          for keyword in keywords:
              self.fyi("keyword: %s" % keyword)
              if strict_match:
                  self.fyi("strict match on keyword '%s'" % keyword)
                  try:
                      keywordId = self.con.execute("SELECT keywordId FROM keyword WHERE keyword=?;",
                              [keyword]).fetchone()
                  except:
                      self.error("cannot look up keyword '%s'" % [keyword])
              else:
                  self.fyi("non-strict match on keyword '%s'" % keyword)
                  try:
                      keywordId = []
                      for k in self.cur.execute("SELECT keywordId FROM keyword WHERE keyword=? COLLATE NOCASE;", [keyword]).fetchall():
                          keywordId.extend(k)
                  except:
                      self.error("cannot look up keyword '%s'" % [keyword])
              try:
                  if len(keywordId):
                      self.fyi("looking for noteID matches to keywordId %s" % keywordId)
                      for k in keywordId:
                          self.fyi("k: %s" % k)
                          try:
                              if strict_match:
                                  noteIdtest = self.cur.execute("SELECT noteId FROM notekeyword WHERE keywordId=?;", [k])
                              else:
                                  noteIdtest = self.cur.execute("SELECT noteId FROM notekeyword WHERE keywordId=? COLLATE NOCASE;", [k])
                          except:
                              self.error("cannot query database to find noteId corresponding to keywordId value %s" % [k])
                          for noteId in noteIdtest:
                              self.fyi("got match to noteID %s" % noteId)
                              if noteId not in noteIds:
                                  noteIds.append(noteId)
                                  self.fyi("adding to list")
                              else:
                                  self.fyi("already in list")
                          self.fyi("done with keyword %s" % k)
                  else:
                      pass
              except:
                  #20150314 self.error("problem finding keyword or note in database")
                  #20150314 shouldn't be an error to not find a note!
                  pass
          ## convert from hash to ids. Note that one hash may create several ids.
          self.fyi("noteIds: %s" % noteIds)
          ## Find IDs of just the notes with the proper book value
          noteIds2 = []
          self.fyi("ORIGINAL noteIds: %s" % noteIds)
          for n in noteIds:
              self.fyi("n=%s" % n)
              try:
                  row = self.cur.execute("SELECT noteId, book FROM note WHERE noteID=?;", n).fetchone()
              except:
                  self.error("cannot look up noteId %s" % n)
              self.fyi("row %s; book=%s" % (row, book))
              if book < 0 or row[1] == book:
                  self.fyi("appending id %s" % row[0])
                  noteIds2.append((row[0],))
              else:
                  self.fyi("skipping id %s because book is wrong" % row[0])
          noteIds = noteIds2
          #self.fyi("  LATER    noteIds2: %s" % noteIds2)
          #self.fyi("  LATER    noteIds: %s" % noteIds)
          rval = []
          for n in noteIds:
              #self.fyi(" processing id=%s" % n)
              try:
                  note = self.cur.execute("SELECT noteId, authorId, date, title, content, due, privacy, modified, hash, book FROM note WHERE noteId=?;", n).fetchone()
              except:
                  self.warning("Problem extracting note %s from database" % n)
                  next
              if note:
                  date = note[2]
                  due = note[5]
                  privacy = note[6]
                  keywordIds = []
                  keywordIds.extend(self.con.execute("SELECT keywordid FROM notekeyword WHERE notekeyword.noteid=?;", n))
                  keywords = []
                  for k in keywordIds:
                      keywords.append(self.cur.execute("SELECT keyword FROM keyword WHERE keywordId=?;", k).fetchone()[0])
                  rval.append({"noteId":note[0], "title":note[3], "keywords":keywords,
                      "content":note[4], "due":note[5], "privacy":note[6],
                      "date":note[2], "modified":note[7], "hash":note[8], "book":note[9]})
          return rval