Piki is a minimal wiki
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

search.py 2.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. from django.conf import settings
  2. import fstools
  3. import logging
  4. import os
  5. from whoosh.fields import Schema, ID, TEXT
  6. from whoosh.qparser.dateparse import DateParserPlugin
  7. from whoosh import index, qparser
  8. from pages.page import base_page
  9. logger = logging.getLogger(settings.ROOT_LOGGER_NAME).getChild(__name__)
  10. SCHEMA = Schema(
  11. id=ID(unique=True, stored=True),
  12. # Page
  13. title=TEXT,
  14. page_src=TEXT
  15. )
  16. def mk_whooshpath_if_needed():
  17. if not os.path.exists(settings.WHOOSH_PATH):
  18. fstools.mkdir(settings.WHOOSH_PATH)
  19. def create_index():
  20. mk_whooshpath_if_needed()
  21. logger.debug('Search Index created.')
  22. return index.create_in(settings.WHOOSH_PATH, schema=SCHEMA)
  23. def rebuild_index(ix):
  24. page_path = fstools.dirlist(settings.PAGES_ROOT, rekursive=False)
  25. for path in page_path:
  26. bp = base_page(path)
  27. add_item(ix, bp)
  28. return len(page_path)
  29. def load_index():
  30. mk_whooshpath_if_needed()
  31. try:
  32. ix = index.open_dir(settings.WHOOSH_PATH)
  33. except index.EmptyIndexError:
  34. ix = create_index()
  35. else:
  36. logger.debug('Search Index opened.')
  37. return ix
  38. def add_item(ix, bp: base_page):
  39. # Define Standard data
  40. #
  41. data = dict(
  42. id=bp.rel_path,
  43. title=bp.title,
  44. page_src=bp.raw_page_src
  45. )
  46. with ix.writer() as w:
  47. logger.info('Adding document with id=%s to the search index.', data.get('id'))
  48. w.add_document(**data)
  49. for key in data:
  50. logger.debug(' - Adding %s=%s', key, repr(data[key]))
  51. def whoosh_search(search_txt):
  52. ix = load_index()
  53. qp = qparser.MultifieldParser(['title', 'page_src'], ix.schema)
  54. qp.add_plugin(DateParserPlugin(free=True))
  55. try:
  56. q = qp.parse(search_txt)
  57. except AttributeError:
  58. return None
  59. except Exception:
  60. return None
  61. with ix.searcher() as s:
  62. results = s.search(q, limit=None)
  63. rpl = []
  64. for hit in results:
  65. rpl.append(hit['id'])
  66. return rpl
  67. def delete_item(ix, bp: base_page):
  68. with ix.writer() as w:
  69. logger.info('Removing document with id=%s from the search index.', bp.rel_path)
  70. w.delete_by_term("task_id", bp.rel_path)
  71. def update_item(bp: base_page):
  72. ix = load_index()
  73. delete_item(ix, bp)
  74. add_item(ix, bp)