+ query = BooleanQuery()
+
+ for fld in fields:
+ tokens = self.get_tokens(searched, fld, cached=tokens_cache)
+
+ query.add(BooleanClause(self.make_term_query(tokens, field=fld,
+ fuzzy=fuzzy), BooleanClause.Occur.SHOULD))
+
+ top = self.searcher.search(query, self.chain_filters(filters), max_results)
+
+ return [SearchResult(self, found, searched=searched, tokens_cache=tokens_cache,
+ snippets=(snippets and self.get_snippets(found, query) or None)) for found in top.scoreDocs]
+
+ def search_perfect_book(self, searched, max_results=20, fuzzy=False, hint=None):
+ """
+ Search for perfect book matches. Just see if the query matches with some author or title,
+ taking hints into account.
+ """
+ fields_to_search = ['authors', 'title']
+ only_in = None
+ if hint:
+ if not hint.should_search_for_book():
+ return []
+ fields_to_search = hint.just_search_in(fields_to_search)
+ only_in = hint.book_filter()
+
+ qrys = [self.make_phrase(self.get_tokens(searched, field=fld), field=fld, fuzzy=fuzzy) for fld in fields_to_search]
+
+ books = []
+ for q in qrys:
+ top = self.searcher.search(q,
+ self.chain_filters([only_in, self.term_filter(Term('is_book', 'true'))]),
+ max_results)
+ for found in top.scoreDocs:
+ books.append(SearchResult(self, found, how_found="search_perfect_book"))
+ return books
+
+ def search_book(self, searched, max_results=20, fuzzy=False, hint=None):
+ fields_to_search = ['tags', 'authors', 'title']
+
+ only_in = None
+ if hint:
+ if not hint.should_search_for_book():
+ return []
+ fields_to_search = hint.just_search_in(fields_to_search)
+ only_in = hint.book_filter()
+
+ tokens = self.get_tokens(searched, field='SIMPLE')
+
+ q = BooleanQuery()
+
+ for fld in fields_to_search:
+ q.add(BooleanClause(self.make_term_query(tokens, field=fld,
+ fuzzy=fuzzy), BooleanClause.Occur.SHOULD))
+
+ books = []
+ top = self.searcher.search(q,
+ self.chain_filters([only_in, self.term_filter(Term('is_book', 'true'))]),
+ max_results)
+ for found in top.scoreDocs:
+ books.append(SearchResult(self, found, how_found="search_book"))
+
+ return books
+
+ def search_perfect_parts(self, searched, max_results=20, fuzzy=False, hint=None):
+ """
+ Search for book parts which contains a phrase perfectly matching (with a slop of 2, default for make_phrase())
+ some part/fragment of the book.
+ """
+ qrys = [self.make_phrase(self.get_tokens(searched), field=fld, fuzzy=fuzzy) for fld in ['content']]
+
+ flt = None
+ if hint:
+ flt = hint.part_filter()
+
+ books = []
+ for q in qrys:
+ top = self.searcher.search(q,
+ self.chain_filters([self.term_filter(Term('is_book', 'true'), inverse=True),
+ flt]),
+ max_results)
+ for found in top.scoreDocs:
+ books.append(SearchResult(self, found, snippets=self.get_snippets(found, q), how_found='search_perfect_parts'))
+
+ return books
+
+ def search_everywhere(self, searched, max_results=20, fuzzy=False, hint=None, tokens_cache=None):
+ """
+ Tries to use search terms to match different fields of book (or its parts).
+ E.g. one word can be an author survey, another be a part of the title, and the rest
+ are some words from third chapter.
+ """
+ if tokens_cache is None: tokens_cache = {}
+ books = []
+ only_in = None
+
+ if hint:
+ only_in = hint.part_filter()
+
+ # content only query : themes x content
+ q = BooleanQuery()
+
+ tokens_pl = self.get_tokens(searched, field='content', cached=tokens_cache)
+ tokens = self.get_tokens(searched, field='SIMPLE', cached=tokens_cache)
+
+ # only search in themes when we do not already filter by themes
+ if hint is None or hint.just_search_in(['themes']) != []:
+ q.add(BooleanClause(self.make_term_query(tokens_pl, field='themes_pl',
+ fuzzy=fuzzy), BooleanClause.Occur.MUST))
+
+ q.add(BooleanClause(self.make_term_query(tokens_pl, field='content',
+ fuzzy=fuzzy), BooleanClause.Occur.SHOULD))
+
+ topDocs = self.searcher.search(q, only_in, max_results)
+ for found in topDocs.scoreDocs:
+ books.append(SearchResult(self, found, how_found='search_everywhere_themesXcontent', searched=searched))
+ print "* %s theme x content: %s" % (searched, books[-1]._hits)
+
+ # query themes/content x author/title/tags
+ q = BooleanQuery()
+ in_content = BooleanQuery()
+ in_meta = BooleanQuery()
+
+ for fld in ['themes_pl', 'content']:
+ in_content.add(BooleanClause(self.make_term_query(tokens_pl, field=fld, fuzzy=False), BooleanClause.Occur.SHOULD))
+
+ for fld in ['tags', 'authors', 'title']:
+ in_meta.add(BooleanClause(self.make_term_query(tokens, field=fld, fuzzy=False), BooleanClause.Occur.SHOULD))
+
+ q.add(BooleanClause(in_content, BooleanClause.Occur.MUST))
+ q.add(BooleanClause(in_meta, BooleanClause.Occur.SHOULD))
+
+ topDocs = self.searcher.search(q, only_in, max_results)
+ for found in topDocs.scoreDocs:
+ books.append(SearchResult(self, found, how_found='search_everywhere', searched=searched))
+ print "* %s scatter search: %s" % (searched, books[-1]._hits)
+
+ return books
+
+ # def multisearch(self, query, max_results=50):
+ # """
+ # Search strategy:
+ # - (phrase) OR -> content
+ # -> title
+ # -> authors
+ # - (keywords) -> authors
+ # -> motyw
+ # -> tags
+ # -> content
+ # """
+ # queryreader = StringReader(query)
+ # tokens = self.get_tokens(queryreader)
+
+ # top_level = BooleanQuery()
+ # Should = BooleanClause.Occur.SHOULD
+
+ # phrase_level = BooleanQuery()
+ # phrase_level.setBoost(1.3)
+
+ # p_content = self.make_phrase(tokens, joined=True)
+ # p_title = self.make_phrase(tokens, 'title')
+ # p_author = self.make_phrase(tokens, 'author')
+
+ # phrase_level.add(BooleanClause(p_content, Should))
+ # phrase_level.add(BooleanClause(p_title, Should))
+ # phrase_level.add(BooleanClause(p_author, Should))
+
+ # kw_level = BooleanQuery()
+
+ # kw_level.add(self.make_term_query(tokens, 'author'), Should)
+ # j_themes = self.make_term_query(tokens, 'themes', joined=True)
+ # kw_level.add(j_themes, Should)
+ # kw_level.add(self.make_term_query(tokens, 'tags'), Should)
+ # j_con = self.make_term_query(tokens, joined=True)
+ # kw_level.add(j_con, Should)
+
+ # top_level.add(BooleanClause(phrase_level, Should))
+ # top_level.add(BooleanClause(kw_level, Should))
+
+ # return None
+
+ def get_snippets(self, scoreDoc, query, field='content'):