results method

Stream<TermSearchResult<T>> results()

Executes a search and returns a stream of individual term results, unsorted and unfiltered.

Implementation

Stream<TermSearchResult<T>> results() {
  final FullTextSearch<T> search = this;
  final Set<String> terms = search.term
      .toString()
      .split(searchTermTokenizer)
      .where((_) => _ != '')
      .toSet();

  Stream<TokenizedItem<T>> tokens = (search.items).map((item) {
    final tokens = search.tokenize(item).map((t) {
      if (t == null) return null;
      if (t is FTSToken) {
        return t;
      } else {
        return FTSToken('$t');
      }
    }).notNullSet();
    return TokenizedItem(tokens, item);
  });
  Stream<TermSearchResult<T>> matches =
      tokens.expand((TokenizedItem<T> item) {
    // Creates a cross-product of tokens and terms
    Iterable<TermMatch> matching = item.tokens.expand((token) {
      return terms.expand((_term) {
        for (final matcher in matchers) {
          final matches = matcher.apply(this, item, _term, token);
          if (matches.isNotEmpty) {
            return matches;
          }
        }
        return const [];
      });
    });

    if (matching.isEmpty) return [];

    final matchedTerms =
        matching.map((TermMatch match) => match.term).toSet();
    final matchedTokens = matching.toSet();
    final termResult = TermSearchResult(
      item.result,
      matchedTerms,
      matchedTokens,
      matchedTerms.length >= terms.length,
    );
    log.fine('Scorers: $scorers');
    search.scorers.forEach(
        (scorer) => scorer.scoreTerm(search, termResult, termResult.score));
    termResult.scoreValue;
    return [termResult];
  });

  return matches;
}